using System.Collections.Generic; using System.Linq; using UnityEngine; namespace Entity { public class Inventory { public Entity From { get; private set; } private readonly List _slots; public int Capacity { get; private set; } public event System.Action OnItemAdded; public event System.Action OnItemRemoved; public event System.Action OnInventoryChanged; public Inventory(Entity owner, int capacity = 20) { From = owner; Capacity = Mathf.Max(1, capacity); _slots = new List(Capacity); } public int AddItem(Item.ItemResource itemResource, int quantity) { if (itemResource == null || quantity <= 0) { Debug.LogWarning( $"Inventory for {From?.ToString() ?? "Unknown"}: Attempted to add null item or zero/negative quantity."); return quantity; } var remainingQuantity = quantity; var addedTotal = 0; // 1. 尝试堆叠到现有槽位 (使用 DefName 进行比较) if (itemResource.MaxStack > 1) { foreach (var slot in _slots.Where(s => s.Item != null && s.Item.DefName == itemResource.DefName && !s.IsFull)) { var addedToSlot = slot.AddQuantity(remainingQuantity); remainingQuantity -= addedToSlot; addedTotal += addedToSlot; if (remainingQuantity <= 0) break; } } // 2. 如果还有剩余,尝试添加到新槽位 while (remainingQuantity > 0 && _slots.Count < Capacity) { var quantityToAdd = Mathf.Min(remainingQuantity, itemResource.MaxStack); var newSlot = new InventorySlot(itemResource, quantityToAdd); _slots.Add(newSlot); remainingQuantity -= quantityToAdd; addedTotal += quantityToAdd; } if (addedTotal > 0) { OnItemAdded?.Invoke(itemResource, addedTotal); OnInventoryChanged?.Invoke(); } if (remainingQuantity > 0) { Debug.LogWarning( $"Inventory for {From?.ToString() ?? "Unknown"} is full or cannot stack. {remainingQuantity} of {itemResource.Name} (DefName: {itemResource.DefName}) could not be added."); } return remainingQuantity; } public int RemoveItem(Item.ItemResource itemResource, int quantity) { if (itemResource == null || quantity <= 0) { Debug.LogWarning( $"Inventory for {From?.ToString() ?? "Unknown"}: Attempted to remove null item or zero/negative quantity."); return quantity; } var remainingQuantity = quantity; var removedTotal = 0; var slotsToClean = new List(); // 从后往前遍历,以便安全地移除空槽位 (使用 DefName 进行比较) for (var i = _slots.Count - 1; i >= 0; i--) { var slot = _slots[i]; if (slot.Item != null && slot.Item.DefName == itemResource.DefName) { var removedFromSlot = slot.RemoveQuantity(remainingQuantity); remainingQuantity -= removedFromSlot; removedTotal += removedFromSlot; if (slot.IsEmpty) { slotsToClean.Add(slot); } if (remainingQuantity <= 0) break; } } foreach (var slot in slotsToClean) { _slots.Remove(slot); } if (removedTotal > 0) { OnItemRemoved?.Invoke(itemResource, removedTotal); OnInventoryChanged?.Invoke(); } if (remainingQuantity > 0) { Debug.LogWarning( $"Inventory for {From?.ToString() ?? "Unknown"}: Not enough {itemResource.Name} (DefName: {itemResource.DefName}). {remainingQuantity} could not be removed."); } return remainingQuantity; } public bool HasItem(Item.ItemResource itemResource, int quantity = 1) { if (itemResource == null || quantity <= 0) return false; return GetItemCount(itemResource) >= quantity; } public int GetItemCount(Item.ItemResource itemResource) { if (itemResource == null) return 0; // 使用 DefName 进行计数 return _slots.Where(s => s.Item != null && s.Item.DefName == itemResource.DefName) .Sum(s => s.Quantity); } public IReadOnlyList GetSlots() { return _slots.AsReadOnly(); } public InventorySlot GetSlot(Item.ItemResource itemResource) { if (itemResource == null) return null; foreach (var slot in _slots) { if (slot.Item != null && slot.Item.DefName == itemResource.DefName) { return slot; } } return null; } public InventorySlot GetSlot(int i) { if (i < 0 || i >= OccupiedSlotsCount) return null; return _slots[i]; } public int OccupiedSlotsCount => _slots.Count; public int AvailableSlotsCount => Capacity - _slots.Count; } }