186 lines
4.7 KiB
C#
186 lines
4.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Events;
|
|
|
|
[Serializable]
|
|
public class InventoryItemStack
|
|
{
|
|
public InventoryItemType itemType;
|
|
[Min(0)] public int count;
|
|
}
|
|
|
|
[Serializable]
|
|
public class InventoryItemChangedEvent : UnityEvent<InventoryItemType, int>
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// 실제 아이템 개수를 관리하는 중심 스크립트입니다.
|
|
/// UI를 직접 수정하지 않고, 아이템 개수 변경 이벤트만 알려줍니다.
|
|
/// </summary>
|
|
[DisallowMultipleComponent]
|
|
public class InventoryManager : MonoBehaviour
|
|
{
|
|
[Header("Initial Items")]
|
|
[SerializeField] private List<InventoryItemStack> initialItems = new List<InventoryItemStack>();
|
|
|
|
[Header("Events")]
|
|
public InventoryItemChangedEvent onItemCountChanged;
|
|
public UnityEvent onInventoryChanged;
|
|
|
|
[Header("Debug")]
|
|
[SerializeField] private bool showDebugLog = true;
|
|
|
|
private readonly Dictionary<InventoryItemType, int> itemCounts = new Dictionary<InventoryItemType, int>();
|
|
|
|
public event Action<InventoryItemType, int> ItemCountChanged;
|
|
public event Action InventoryChanged;
|
|
|
|
private void Awake()
|
|
{
|
|
InitializeFromInspector();
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
NotifyAllItemsChanged();
|
|
}
|
|
|
|
private void InitializeFromInspector()
|
|
{
|
|
itemCounts.Clear();
|
|
|
|
foreach (InventoryItemType itemType in Enum.GetValues(typeof(InventoryItemType)))
|
|
itemCounts[itemType] = 0;
|
|
|
|
for (int i = 0; i < initialItems.Count; i++)
|
|
{
|
|
InventoryItemStack stack = initialItems[i];
|
|
if (stack == null)
|
|
continue;
|
|
|
|
itemCounts[stack.itemType] = Mathf.Max(0, stack.count);
|
|
}
|
|
}
|
|
|
|
public void AddItem(InventoryItemType itemType)
|
|
{
|
|
AddItem(itemType, 1);
|
|
}
|
|
|
|
public void AddItem(InventoryItemType itemType, int amount)
|
|
{
|
|
if (amount <= 0)
|
|
return;
|
|
|
|
int newCount = GetItemCount(itemType) + amount;
|
|
SetItemCount(itemType, newCount);
|
|
|
|
if (showDebugLog)
|
|
Debug.Log($"[InventoryManager] {itemType} +{amount} => {newCount}");
|
|
}
|
|
|
|
public bool RemoveItem(InventoryItemType itemType)
|
|
{
|
|
return RemoveItem(itemType, 1);
|
|
}
|
|
|
|
public bool RemoveItem(InventoryItemType itemType, int amount)
|
|
{
|
|
if (amount <= 0)
|
|
return false;
|
|
|
|
int current = GetItemCount(itemType);
|
|
|
|
if (current < amount)
|
|
{
|
|
if (showDebugLog)
|
|
Debug.LogWarning($"[InventoryManager] {itemType} 부족: 현재 {current}, 필요 {amount}");
|
|
|
|
return false;
|
|
}
|
|
|
|
SetItemCount(itemType, current - amount);
|
|
return true;
|
|
}
|
|
|
|
public void SetItemCount(InventoryItemType itemType, int count)
|
|
{
|
|
int clampedCount = Mathf.Max(0, count);
|
|
int previousCount = GetItemCount(itemType);
|
|
|
|
if (previousCount == clampedCount)
|
|
return;
|
|
|
|
itemCounts[itemType] = clampedCount;
|
|
NotifyItemChanged(itemType, clampedCount);
|
|
}
|
|
|
|
public int GetItemCount(InventoryItemType itemType)
|
|
{
|
|
if (itemCounts.TryGetValue(itemType, out int count))
|
|
return count;
|
|
|
|
return 0;
|
|
}
|
|
|
|
public bool HasItem(InventoryItemType itemType)
|
|
{
|
|
return GetItemCount(itemType) > 0;
|
|
}
|
|
|
|
public bool HasItem(InventoryItemType itemType, int requiredAmount)
|
|
{
|
|
return GetItemCount(itemType) >= Mathf.Max(1, requiredAmount);
|
|
}
|
|
|
|
public void ClearInventory()
|
|
{
|
|
foreach (InventoryItemType itemType in Enum.GetValues(typeof(InventoryItemType)))
|
|
itemCounts[itemType] = 0;
|
|
|
|
NotifyAllItemsChanged();
|
|
}
|
|
|
|
public IReadOnlyDictionary<InventoryItemType, int> GetAllItemCounts()
|
|
{
|
|
return itemCounts;
|
|
}
|
|
|
|
private void NotifyItemChanged(InventoryItemType itemType, int count)
|
|
{
|
|
ItemCountChanged?.Invoke(itemType, count);
|
|
InventoryChanged?.Invoke();
|
|
|
|
onItemCountChanged?.Invoke(itemType, count);
|
|
onInventoryChanged?.Invoke();
|
|
}
|
|
|
|
private void NotifyAllItemsChanged()
|
|
{
|
|
foreach (KeyValuePair<InventoryItemType, int> pair in itemCounts)
|
|
{
|
|
ItemCountChanged?.Invoke(pair.Key, pair.Value);
|
|
onItemCountChanged?.Invoke(pair.Key, pair.Value);
|
|
}
|
|
|
|
InventoryChanged?.Invoke();
|
|
onInventoryChanged?.Invoke();
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
private void OnValidate()
|
|
{
|
|
if (initialItems == null)
|
|
return;
|
|
|
|
for (int i = 0; i < initialItems.Count; i++)
|
|
{
|
|
if (initialItems[i] != null)
|
|
initialItems[i].count = Mathf.Max(0, initialItems[i].count);
|
|
}
|
|
}
|
|
#endif
|
|
}
|