(client) feat:实现热重载,实现多维度,实现武器,实现掉落物,实现状态UI,实现攻击AI (#44)

Co-authored-by: zzdxxz <2079238449@qq.com>
Co-committed-by: zzdxxz <2079238449@qq.com>
This commit is contained in:
2025-08-27 19:56:49 +08:00
committed by TheRedApricot
parent d91210a6ff
commit 8456b6c162
132 changed files with 18568 additions and 2534 deletions

View File

@ -1,70 +1,169 @@
using System.Collections.Generic;
using System.Linq;
using Item;
using UnityEngine;
namespace Entity
{
public class Inventory
{
public Entity from; // 物品所属实体
public List<ItemBase> items = new List<ItemBase>(); // 背包中的物品列表
public Entity From { get; private set; }
private readonly List<InventorySlot> _slots;
public int Capacity { get; private set; }
/// <summary>
/// 添加物品到背包
/// </summary>
/// <param name="item">要添加的物品</param>
/// <param name="count">添加的数量</param>
public void AddItem(ItemResource resource, int count)
public event System.Action<Item.ItemResource, int> OnItemAdded;
public event System.Action<Item.ItemResource, int> OnItemRemoved;
public event System.Action OnInventoryChanged;
public Inventory(Entity owner, int capacity = 20)
{
if (count <= 0) return; // 如果数量小于等于0直接返回
From = owner;
Capacity = Mathf.Max(1, capacity);
_slots = new List<InventorySlot>(Capacity);
}
// 检查背包中是否已存在相同物品
foreach (var item in items)
public int AddItem(Item.ItemResource itemResource, int quantity)
{
if (itemResource == null || quantity <= 0)
{
if (item.resource.Equals(resource))
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))
{
item.count += count; // 增加数量
return;
var addedToSlot = slot.AddQuantity(remainingQuantity);
remainingQuantity -= addedToSlot;
addedTotal += addedToSlot;
if (remainingQuantity <= 0) break;
}
}
// 如果没有找到相同物品,则创建新物品并添加到背包
var newItem = new ItemBase { resource = resource, count = count };
items.Add(newItem);
// 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;
}
/// <summary>
/// 从背包中取出物品
/// </summary>
/// <param name="itemName">物品名称</param>
/// <param name="count">取出的数量</param>
/// <returns>是否成功取出</returns>
public bool RemoveItem(string itemName, int count)
public int RemoveItem(Item.ItemResource itemResource, int quantity)
{
if (count <= 0) return false; // 如果数量小于等于0直接返回失败
foreach (var item in items)
if (itemResource == null || quantity <= 0)
{
if (item.resource.name == itemName)
{
if (item.count >= count)
{
item.count -= count; // 减少数量
if (item.count == 0)
{
items.Remove(item); // 如果数量为0则移除该物品
}
Debug.LogWarning(
$"Inventory for {From?.ToString() ?? "Unknown"}: Attempted to remove null item or zero/negative quantity.");
return quantity;
}
return true; // 成功取出
}
else
var remainingQuantity = quantity;
var removedTotal = 0;
var slotsToClean = new List<InventorySlot>();
// 从后往前遍历,以便安全地移除空槽位 (使用 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)
{
return false; // 数量不足
slotsToClean.Add(slot);
}
if (remainingQuantity <= 0) break;
}
}
return false; // 未找到物品
}
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<InventorySlot> 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;
}
}