using System; using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine; namespace BrewMonster.Scripts.Managers { /// /// C# mirror of C++ CECInventory (EC_Inventory.h / EC_Inventory.cpp). /// Instance-based inventory core plus static helpers used by existing client code. /// public class EC_Inventory { // ===== Instance-based inventory (per-pack) ===== // Item array: index is slot, null means empty. private EC_IvtrItem[] m_aItems = Array.Empty(); public static class Inventory_type { public const int IVTRTYPE_PACK = 0, // Normal pack IVTRTYPE_EQUIPPACK = 1, // Equipment IVTRTYPE_TASKPACK = 2, // Task pack IVTRTYPE_TRASHBOX = 3, // Trash box IVTRTYPE_TRASHBOX2 = 4, // Trash box - material box IVTRTYPE_TRASHBOX3 = 5, // Trash box - fashion box IVTRTYPE_ACCOUNT_BOX = 6, // User account box IVTRTYPE_GENERALCARD_BOX = 7; // ���ư��� }; // ע�� IVTRTYPE_CLIENT_GENERALCARD_PACK ö��ֵ���ܺ������ Inventory type ֵ�ظ����� public static class IVTRTYPE_PACK_CLIENT_GENERALCAR { public const int IVTRTYPE_CLIENT_GENERALCARD_PACK = 1024; // �ͻ��˱��ذ����� ���ڿ���ͼ��Ҫ����ѻ�ÿ���ͨ�����췢�͡�Ϊ��ͳһ�������촰�ڵ���Ʒ�����ӱ��ذ����� }; public EC_Inventory() { } public bool Init(int iSize) { Resize(iSize); return true; } public void Release() { // In C++ this deletes all heap-allocated items. // Here we simply clear references so GC can collect them. RemoveAllItems(); m_aItems = Array.Empty(); } public void RemoveAllItems() { for (int i = 0; i < m_aItems.Length; i++) { m_aItems[i] = null; } } public void Resize(int iNewSize) { int oldSize = m_aItems.Length; if (iNewSize < 0) iNewSize = 0; if (iNewSize == oldSize) return; var newArray = iNewSize > 0 ? new EC_IvtrItem[iNewSize] : Array.Empty(); if (oldSize > 0 && iNewSize > 0) { Array.Copy(m_aItems, newArray, Math.Min(oldSize, iNewSize)); } m_aItems = newArray; } public EC_IvtrItem PutItem(int iSlot, EC_IvtrItem pItem) { if (iSlot < 0 || iSlot >= m_aItems.Length) { return null; } var old = m_aItems[iSlot]; m_aItems[iSlot] = pItem; return old; } public void SetItem(int iSlot, EC_IvtrItem pItem) { if (iSlot < 0 || iSlot >= m_aItems.Length) { return; } m_aItems[iSlot] = pItem; } public EC_IvtrItem GetItem(int iSlot, bool bRemove = false) { if (iSlot < 0 || iSlot >= m_aItems.Length) { return null; } var pItem = m_aItems[iSlot]; if (bRemove) m_aItems[iSlot] = null; return pItem; } public void ExchangeItem(int iSlot1, int iSlot2) { if (iSlot1 < 0 || iSlot1 >= m_aItems.Length || iSlot2 < 0 || iSlot2 >= m_aItems.Length) { return; } if (iSlot1 == iSlot2) return; var tmp = m_aItems[iSlot1]; m_aItems[iSlot1] = m_aItems[iSlot2]; m_aItems[iSlot2] = tmp; } public bool MergeItem(int tid, int iExpireDate, int iAmount, out int piLastSlot, out int piLastAmount) { piLastSlot = -1; piLastAmount = 0; int firstEmpty = -1; for (int i = 0; i < m_aItems.Length; i++) { var slotItem = m_aItems[i]; if (slotItem != null) { if (slotItem.GetTemplateID() != tid) continue; int pileLimit = Math.Max(1, EC_IvtrItem.GetPileLimit(tid)); int canAdd = Math.Max(0, pileLimit - Math.Max(0, slotItem.GetCount())); if (canAdd <= 0) continue; int add = Math.Min(canAdd, iAmount); slotItem.AddAmount(add); iAmount -= add; if (iAmount == 0) { piLastSlot = i; piLastAmount = slotItem.GetCount(); return true; } } else if (firstEmpty < 0) { firstEmpty = i; } } if (firstEmpty < 0 || iAmount <= 0) { return false; } var newItem = EC_IvtrItem.CreateItem(tid, iExpireDate, iAmount); newItem.SetCount(iAmount); m_aItems[firstEmpty] = newItem; piLastSlot = firstEmpty; piLastAmount = iAmount; return true; } public bool MoveItem(int iSrc, int iDest, int iAmount) { if (iSrc < 0 || iSrc >= m_aItems.Length || iDest < 0 || iDest >= m_aItems.Length) { return false; } var pSrc = m_aItems[iSrc]; var pDst = m_aItems[iDest]; if (pSrc == null) return false; if (iAmount == 0) return false; if (pDst == null) { var clone = EC_IvtrItem.CreateItem(pSrc.GetTemplateID(), pSrc.GetExpireDate(), iAmount); m_aItems[iDest] = clone; } else { if (pSrc.GetTemplateID() != pDst.GetTemplateID()) return false; int pileLimit = Math.Max(1, EC_IvtrItem.GetPileLimit(pDst.GetTemplateID())); int canAdd = Math.Max(0, pileLimit - Math.Max(0, pDst.GetCount())); int add = Math.Min(canAdd, iAmount); if (add <= 0) return false; pDst.AddAmount(add); iAmount = add; } RemoveItem(iSrc, iAmount); return true; } public bool RemoveItem(int iSlot, int iAmount) { if (iSlot < 0 || iSlot >= m_aItems.Length) { return false; } var pItem = m_aItems[iSlot]; if (pItem == null) return true; int newCount = pItem.AddAmount(-Math.Max(0, iAmount)); if (newCount <= 0) m_aItems[iSlot] = null; return true; } public int FindItem(int idItem, int baseIdx = 0) { if (baseIdx < 0) baseIdx = 0; for (int i = baseIdx; i < m_aItems.Length; i++) { var pItem = m_aItems[i]; if (pItem != null && pItem.GetTemplateID() == idItem) return i; } return -1; } public int GetItemTotalNum(int idItem) { int count = 0; for (int i = 0; i < m_aItems.Length; i++) { var pItem = m_aItems[i]; if (pItem != null && pItem.GetTemplateID() == idItem) count += Math.Max(0, pItem.GetCount()); } return count; } public int SearchEmpty() { for (int i = 0; i < m_aItems.Length; i++) { if (m_aItems[i] == null) return i; } return -1; } public int GetEmptySlotNum() { int count = 0; for (int i = 0; i < m_aItems.Length; i++) { if (m_aItems[i] == null) count++; } return count; } public int CanAddItem(int idItem, int iAmount, bool tryPile) { int foundEmpty = -1; for (int i = 0; i < m_aItems.Length; i++) { var pItem = m_aItems[i]; if (pItem == null) { if (!tryPile) return i; if (foundEmpty < 0) foundEmpty = i; } else if (pItem.GetTemplateID() == idItem) { int pileLimit = Math.Max(1, EC_IvtrItem.GetPileLimit(idItem)); if (pItem.GetCount() + iAmount <= pileLimit) return i; } } return foundEmpty; } public int GetSize() { return m_aItems.Length; } // Unfreeze all items public void UnfreezeAllItems() { // Release all items for (int i=0; i < m_aItems.Length; i++) { if (m_aItems[i] != null) m_aItems[i].Freeze(false); } } } }