Files
test/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs
T
2025-11-20 13:47:10 +07:00

306 lines
8.4 KiB
C#

using System;
using System.Collections.Generic;
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 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 = new EC_IvtrItem(tid, iExpireDate)
{
Slot = firstEmpty,
State = 0,
Crc = 0,
Content = null
};
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 = new EC_IvtrItem(pSrc.GetTemplateID(), pSrc.GetExpireDate())
{
Slot = iDest,
Package = pSrc.Package,
State = pSrc.State,
Crc = pSrc.Crc,
Content = pSrc.Content != null ? (byte[])pSrc.Content.Clone() : null
};
clone.SetCount(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;
}
}
}