Files
2026-01-22 10:02:58 +07:00

320 lines
9.4 KiB
C#

using System;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
namespace BrewMonster.Scripts.Managers
{
/// <summary>
/// C# mirror of C++ CECInventory (EC_Inventory.h / EC_Inventory.cpp).
/// Instance-based inventory core plus static helpers used by existing client code.
/// </summary>
public class EC_Inventory
{
// ===== Instance-based inventory (per-pack) =====
// Item array: index is slot, null means empty.
private EC_IvtrItem[] m_aItems = Array.Empty<EC_IvtrItem>();
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<EC_IvtrItem>();
}
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<EC_IvtrItem>();
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);
}
}
}
}