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 OnItemPickedUp = delegate { }; public event Action OnItemDropped = delegate { }; public event Action 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 // } }