设计一个物品容器,用于物品系统中的核心数据存储

 public class ItemContainer
{
    
    
    private List<InventoryItem> m_List; // 数据队列
    private Dictionary<int, int> checkList; // 检索表
    private List<int> isNullIndexList; // 记录空数据的index

    #region 构造一份容器数据

    public ItemContainer()
    {
    
    
        AllocateMemory();
    }

    // 加载一份容器数据
    public ItemContainer(string loadKey)
    {
    
    
        // 直接加载
        m_List = LoadData(loadKey);
        if (m_List != null)
        {
    
    
            isNullIndexList = new List<int>();
            // 构建检索表
            checkList = new Dictionary<int, int>();
            int index = 0;
            foreach (var item in m_List) checkList.Add(item.itemID, index++);
        }
        else AllocateMemory();
    }

    // 存在预设数据构造容器
    public ItemContainer(List<InventoryItem> dataList)
    {
    
    
        AllocateMemory();
        if (dataList.Count != 0)
        {
    
    
            m_List = dataList;
            // 构建搜索表
            int index = 0;
            foreach (var item in m_List) checkList.Add(item.itemID, index++);
        }
    }

    #endregion

    #region Save/Load 容器数据存储加载

    public void SaveData(string saveKey)
    {
    
    
        UserCenterManager.SaveData(saveKey, GetItemList());
        ClearData();
        Log.D($"[{
      
      saveKey}] Data Saved Successfully");
    }

    private List<InventoryItem> LoadData(string loadKey)
    {
    
    
        // 对这里进行修改!!
        // 加载数据改为加载存档,如果没有返回空,外部自己加载预设,不在这个类做处理
        UserCenterManager.LoadData(loadKey, out List<InventoryItem> loadData, null);
        Log.D($"[{
      
      loadKey}] Data Loaded Successfully");
        return loadData;
    }

    #endregion

    #region SET

    /// <summary>
    /// 在后面增加一段物品数据
    /// </summary>
    /// <param name="itemList"></param>
    public void AddRange(List<InventoryItem> itemList)
    {
    
    
        m_List.AddRange(itemList);
    }

    /// <summary>
    /// 增加指定数量的物品
    /// </summary>
    /// <param name="ID">物品ID</param>
    /// <param name="amount">数量</param>
    public void AddItemAmount(int ID, int amount)
    {
    
    
        var index = GetIndexInListByID(ID);
        // 如果列表中没这个物品,列表中增加一个,并且增加一个检索表
        if (index == -1)
        {
    
    
            var item = new InventoryItem {
    
     itemID = ID, itemAmount = amount };

            // 返回空数据的首个index
            var isNoneIndex = GetListHasNullIndex();
            int addIndex = isNoneIndex != -1 ? isNoneIndex : m_List.Count;

            // 先处理索引,后处理list
            checkList.Add(ID, addIndex);
            // 当为-1时,说明不需要从index表中删除索引,或者addIndex==m_List.count时
            if (isNoneIndex != -1) isNullIndexList.Remove(isNoneIndex);
            // 如果有空的位置替换,没有追加
            if (addIndex < m_List.Count) m_List[isNoneIndex] = item;
            else m_List.Add(item);
        }
        else // 列表中有该物品
        {
    
    
            int currentAmount = m_List[index].itemAmount + amount;
            var item = new InventoryItem {
    
     itemID = ID, itemAmount = currentAmount };
            m_List[index] = item;
        }
    }

    /// <summary>
    /// 移除指定数量的物品,并返回实际删除数量
    /// </summary>
    /// <param name="ID">物品ID</param>
    /// <param name="removeAmount">数量</param>
    public int RemoveItem(int ID, int removeAmount)
    {
    
    
        // 需要删除的物品一定存在index 不能存在返回
        int index = GetIndexInListByID(ID);
        if (index == -1)
        {
    
    
            Log.D($"物品{
      
      ID}并不存在,执行失败");
            return -1;
        }

        // 获得实际删除的数值
        int real = m_List[index].itemAmount >= removeAmount ? removeAmount : m_List[index].itemAmount;
        // 如果物品还有剩余,修改list内容
        if (m_List[index].itemAmount > removeAmount)
        {
    
    
            int currentAmount = m_List[index].itemAmount - removeAmount;
            var item = new InventoryItem {
    
     itemID = ID, itemAmount = currentAmount };
            m_List[index] = item;
        }
        else if (m_List[index].itemAmount == removeAmount)
        {
    
    
            // 此时物品数量为0,将数据置空,也可以不做修改。
            m_List[index] = new InventoryItem {
    
     itemID = 0, itemAmount = 0 };
            // 将物品ID从checkList中删除
            checkList.Remove(ID);
            // 记录删除位置的index,用于下次新增覆盖
            isNullIndexList.Add(index);
        }
        else
        {
    
    
            var residue = removeAmount - m_List[index].itemAmount;
            m_List[index] = new InventoryItem {
    
     itemID = 0, itemAmount = 0 };
            // 将物品ID从checkList中删除
            checkList.Remove(ID);
            // 记录删除位置的index,用于下次新增覆盖
            isNullIndexList.Add(index);

            Log.D($"减去超载{
      
      residue}" !);
        }

        return real;
    }

    /// <summary>
    /// 通过ID直接删除某一物品,并返回被删除数量
    /// </summary>
    /// <param name="ID"></param>
    /// <returns></returns>
    public int RemoveItemByID(int ID)
    {
    
    
        int index = GetIndexInListByID(ID);
        if (index == -1)
        {
    
    
            Log.D($"物品{
      
      ID}并不存在,执行失败");
            return -1;
        }

        int real = m_List[index].itemAmount;
        m_List[index] = new InventoryItem {
    
     itemID = 0, itemAmount = 0 };
        // 将物品ID从checkList中删除
        checkList.Remove(ID);
        // 记录删除位置的index,用于下次新增覆盖
        isNullIndexList.Add(index);
        return real;
    }

    /// <summary>
    /// 修改某一物品数量
    /// </summary>
    /// <param name="itemID"></param>
    /// <param name="amount"></param>
    public void ResetItemAmount(int itemID, int amount)
    {
    
    
        RemoveItemByID(itemID);
        AddItemAmount(itemID, amount);
    }

    public void ClearData()
    {
    
    
        m_List.Clear();
        checkList.Clear();
        isNullIndexList.Clear();
    }

    #endregion

    #region GET

    /// <summary>
    /// 容器是否拥有数据
    /// </summary>
    /// <returns></returns>
    public bool IsNoneData()
    {
    
    
        return m_List == null || m_List.Count == 0;
    }

    /// <summary>
    /// 获得真实物品列表 不包含空数据
    /// </summary>
    /// <returns></returns>
    public List<InventoryItem> GetItemList()
    {
    
    
        List<InventoryItem> resList = new List<InventoryItem>();
        // 如果置空表里面存在数据,则从list里剔除
        foreach (var n in checkList)
        {
    
    
            resList.Add(m_List[n.Value]);
        }

        return resList;
    }

    /// <summary>
    /// 是否包含某个物品
    /// </summary>
    /// <param name="itemID"></param>
    /// <returns></returns>
    public bool IsHasItem(int itemID)
    {
    
    
        return checkList.ContainsKey(itemID);
    }

    /// <summary>
    /// 包含所有物品ID
    /// </summary>
    /// <returns></returns>
    public Dictionary<int, int>.KeyCollection GetCheckListKeys()
    {
    
    
        return checkList.Keys;
    }

    /// <summary>
    /// 通过物品ID获得数据详情
    /// </summary>
    /// <param name="itemID"></param>
    /// <returns></returns>
    public InventoryItem GetItemData(int itemID)
    {
    
    
        if (checkList.ContainsKey(itemID))
        {
    
    
            var index = checkList[itemID];
            return m_List[index];
        }

        return new InventoryItem(itemID, 0);
    }
    
    #endregion

    #region 其他Helpper函数

    // 通过物品ID找到物品在list中的位置 -1则没有这个物品否则返回序号
    private int GetIndexInListByID(int ID)
    {
    
    
        return checkList.ContainsKey(ID) ? checkList[ID] : -1;
    }

    // 返回一个可用于添加的位置
    private int GetListHasNullIndex()
    {
    
    
        return isNullIndexList.Count != 0 ? isNullIndexList[0] : -1;
    }

    // 分配内存
    private void AllocateMemory()
    {
    
    
        m_List = new List<InventoryItem>();
        checkList = new Dictionary<int, int>();
        isNullIndexList = new List<int>();
    }

    public override string ToString()
    {
    
    
        string str = "DataList \n";
        foreach (var n in m_List)
        {
    
    
            str += $"{
      
      n.itemID}:{
      
      n.itemAmount} / ";
        }

        str += "\n checkListMap\n";
        foreach (var n in checkList)
        {
    
    
            str += $"{
      
      n.Key}:{
      
      n.Value} / ";
        }

        str += "\n isNullIndex\n";
        foreach (var n in isNullIndexList)
        {
    
    
            str += $"{
      
      n} / ";
        }

        return str;
    }

    #endregion
}

猜你喜欢

转载自blog.csdn.net/wankcn/article/details/130769803