using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Sirenix.OdinInspector; using UnityEngine; namespace DDD { public class InventoryManager : Singleton, IManager { [Title("아이템 전체 목록")] [ShowInInspector, ReadOnly] private Dictionary _itemDataLookup; [Title("아이템 보유 목록")] [ShowInInspector, ReadOnly] private Dictionary _inventoryItemDatas; #if UNITY_EDITOR [Title("테스트용")] private InventoryTestDataSo _inventoryTestDataSo; #endif public void PreInit() { } public Task Init() { return Task.CompletedTask; } public void PostInit() { InitializeItemData(); } private void InitializeItemData() { var itemDataSo = DataManager.Instance.ItemDataSo; Debug.Assert(itemDataSo != null, "itemDataSo != null"); _itemDataLookup = itemDataSo.GetDataList() .Where(item => !string.IsNullOrEmpty(item.Id)) .ToDictionary(item => item.Id, item => item); _inventoryItemDatas = new Dictionary(itemDataSo.GetDataCount()); #if UNITY_EDITOR ApplyEditorTestData(); #endif } #if UNITY_EDITOR private async void ApplyEditorTestData() { _inventoryTestDataSo = await AssetManager.LoadAsset(DataConstants.InventoryTestDataSo); if (_inventoryTestDataSo == null || !_inventoryTestDataSo.UseTestData) return; foreach (var entry in _inventoryTestDataSo.TestItems) { if (string.IsNullOrWhiteSpace(entry.ItemId)) continue; AddItem(entry.ItemId, entry.Quantity); } Debug.Log("[InventoryManager] 테스트용 인벤토리 적용 완료"); } #endif public bool AddItem(string id, int quantity = 1) { if (!_itemDataLookup.ContainsKey(id)) { Debug.LogError($"[Inventory] 등록되지 않은 아이템 ID: {id}"); return false; } if (_inventoryItemDatas.TryGetValue(id, out var itemData)) { itemData.Quantity += quantity; } else { _inventoryItemDatas[id] = new InventoryItemData(id, quantity); } InventoryChangedEvent evt = GameEvents.InventoryChangedEvent; evt.ItemId = id; evt.NewCount = GetItemCount(id); EventBus.Broadcast(evt); return true; } public bool RemoveItem(string id, int quantity = 1) { if (!_inventoryItemDatas.TryGetValue(id, out var itemData)) { Debug.LogError($"[Inventory] 등록되지 않은 아이템 ID: {id}"); return false; } if (itemData.Quantity < quantity) { Debug.LogWarning($"[Inventory] 보유 수량보다 삭제하는 수량이 더 많습니다 " + $"{id}, 보유 수량 : {itemData.Quantity}, 삭제 수량 : {quantity}"); return false; } itemData.Quantity -= quantity; if (itemData.Quantity <= 0) { _inventoryItemDatas.Remove(id); } InventoryChangedEvent evt = GameEvents.InventoryChangedEvent; evt.ItemId = id; evt.NewCount = GetItemCount(id); EventBus.Broadcast(evt); return true; } public IReadOnlyDictionary InventoryItems => _inventoryItemDatas; public bool TryGetItemData(string id, out ItemData itemData) => _itemDataLookup.TryGetValue(id, out itemData); public int GetItemCount(string id) => _inventoryItemDatas.TryGetValue(id, out var itemData) ? itemData.Quantity : 0; public ItemData GetItemDataByIdOrNull(string id) { _itemDataLookup.TryGetValue(id, out var itemData); return itemData; } } }