Files
jelito/Assets/jelycho/Code/Items/Inventory.cs

137 lines
4.0 KiB
C#

using System;
using System.Collections.Generic;
using RebootKit.Engine.Foundation;
namespace RebootReality.jelycho.Items {
public class Inventory {
static readonly Logger s_Logger = new Logger(nameof(Inventory));
class SlotState {
public ushort ActorID;
public ItemActor Actor;
public void EmptySlot() {
ActorID = 0;
Actor = null;
}
}
readonly SlotState[] m_Slots;
public event Action<ItemActor> OnItemPickedUp = delegate { };
public event Action<ItemActor> OnItemDropped = delegate { };
public event Action<int> OnSlotUpdated = delegate { };
public int SlotsCount {
get {
return m_Slots.Length;
}
}
public Inventory(int slotsCount) {
m_Slots = new SlotState[slotsCount];
for (int i = 0; i < slotsCount; i++) {
m_Slots[i] = new SlotState();
}
}
//
// @MARK: Server API
//
public bool TryPickup(ItemActor actor) {
if (Contains(actor)) {
s_Logger.Error($"Item {actor.name} is already in the inventory.");
return false;
}
(int slotIndex, SlotState freeItemState) = FindFreeItemState();
if (freeItemState == null) {
s_Logger.Error("Inventory is full, cannot pick up item.");
return false;
}
freeItemState.Actor = actor;
OnItemPickedUp?.Invoke(actor);
OnSlotUpdated?.Invoke(slotIndex);
return true;
}
public bool TryDrop(int slotIndex, out ItemActor actor) {
if (slotIndex < 0 || slotIndex >= m_Slots.Length) {
s_Logger.Error($"Slot index {slotIndex} is out of range.");
actor = null;
return false;
}
if (m_Slots[slotIndex].Actor == null) {
s_Logger.Error($"No items in slot {slotIndex} to drop.");
actor = null;
return false;
}
actor = m_Slots[slotIndex].Actor;
m_Slots[slotIndex].Actor = null;
OnItemDropped?.Invoke(actor);
OnSlotUpdated?.Invoke(slotIndex);
return actor;
}
//
// @MARK: Common API
//
public void SetItem(int slotIndex, ItemActor actor) {
if (slotIndex < 0 || slotIndex >= m_Slots.Length) {
throw new ArgumentOutOfRangeException(nameof(slotIndex), "Slot index is out of range.");
}
if (actor == null) {
m_Slots[slotIndex].EmptySlot();
OnSlotUpdated?.Invoke(slotIndex);
return;
}
if (Contains(actor)) {
s_Logger.Error($"Item {actor.name} is already in the inventory.");
return;
}
m_Slots[slotIndex].Actor = actor;
m_Slots[slotIndex].ActorID = actor.ActorID;
OnSlotUpdated?.Invoke(slotIndex);
}
public ItemActor GetItem(int slotIndex) {
if (slotIndex < 0 || slotIndex >= m_Slots.Length) {
throw new ArgumentOutOfRangeException(nameof(slotIndex), "Slot index is out of range.");
}
return m_Slots[slotIndex].Actor;
}
public bool Contains(ItemActor actor) {
for (int i = 0; i < m_Slots.Length; i++) {
if (m_Slots[i].Actor == actor) {
return true;
}
}
return false;
}
(int slot, SlotState state) FindFreeItemState() {
for (int i = 0; i < m_Slots.Length; i++) {
if (m_Slots[i].Actor == null) {
return (i, m_Slots[i]);
}
}
return (-1, null);
}
//
// @MARK: Client API
//
}
}