Init
This commit is contained in:
368
scripts/inventory/InventoryManager.cs
Normal file
368
scripts/inventory/InventoryManager.cs
Normal file
@ -0,0 +1,368 @@
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
public partial class InventoryManager : Node
|
||||
{
|
||||
// 库存数据结构
|
||||
public class InventoryItem
|
||||
{
|
||||
public string ItemId { get; set; }
|
||||
public int Quantity { get; set; }
|
||||
|
||||
public InventoryItem(string itemId, int quantity = 0)
|
||||
{
|
||||
ItemId = itemId;
|
||||
Quantity = quantity;
|
||||
}
|
||||
}
|
||||
|
||||
// 单例实例
|
||||
private static InventoryManager instance;
|
||||
public static InventoryManager Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
// 库存数据字典 - 物品ID -> 库存项
|
||||
private Dictionary<string, InventoryItem> inventory = new Dictionary<string, InventoryItem>();
|
||||
|
||||
// 线程锁
|
||||
private readonly object inventoryLock = new object();
|
||||
|
||||
// 事件委托
|
||||
public delegate void InventoryChangedEventHandler(string itemId, int oldQuantity, int newQuantity);
|
||||
public event InventoryChangedEventHandler InventoryChanged;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
GD.Print("InventoryManager _Ready 开始");
|
||||
|
||||
// 确保单例
|
||||
if (instance == null)
|
||||
{
|
||||
instance = this;
|
||||
InitializeInventory();
|
||||
}
|
||||
else
|
||||
{
|
||||
GD.PrintErr("InventoryManager 实例已存在!");
|
||||
QueueFree();
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化库存
|
||||
private void InitializeInventory()
|
||||
{
|
||||
GD.Print("初始化库存系统");
|
||||
|
||||
lock (inventoryLock)
|
||||
{
|
||||
// 为所有已知物品创建库存条目(初始数量为0)
|
||||
if (GameData.Instance != null)
|
||||
{
|
||||
var allItems = GameData.Instance.GetAllItems();
|
||||
foreach (var item in allItems)
|
||||
{
|
||||
inventory[item.Key] = new InventoryItem(item.Key, 0);
|
||||
}
|
||||
GD.Print($"初始化了 {inventory.Count} 个物品的库存条目");
|
||||
}
|
||||
else
|
||||
{
|
||||
GD.PrintErr("GameData.Instance 为 null,无法初始化库存");
|
||||
}
|
||||
}
|
||||
|
||||
// 添加一些测试数据
|
||||
AddTestData();
|
||||
}
|
||||
|
||||
// 添加测试数据
|
||||
private void AddTestData()
|
||||
{
|
||||
GD.Print("添加测试库存数据");
|
||||
AddItem("iron_ore", 100);
|
||||
AddItem("copper_ore", 50);
|
||||
AddItem("coal_ore", 75);
|
||||
AddItem("water", 200);
|
||||
AddItem("iron_ingot", 25);
|
||||
AddItem("copper_ingot", 15);
|
||||
}
|
||||
|
||||
// 添加物品到库存
|
||||
public bool AddItem(string itemId, int quantity)
|
||||
{
|
||||
if (quantity <= 0) return false;
|
||||
|
||||
lock (inventoryLock)
|
||||
{
|
||||
int oldQuantity = GetItemQuantityUnsafe(itemId);
|
||||
|
||||
if (!inventory.ContainsKey(itemId))
|
||||
{
|
||||
inventory[itemId] = new InventoryItem(itemId, quantity);
|
||||
}
|
||||
else
|
||||
{
|
||||
inventory[itemId].Quantity += quantity;
|
||||
}
|
||||
|
||||
int newQuantity = inventory[itemId].Quantity;
|
||||
GD.Print($"添加物品: {itemId} +{quantity} (总量: {newQuantity})");
|
||||
|
||||
// 在锁外触发事件
|
||||
CallDeferred(nameof(TriggerInventoryChanged), itemId, oldQuantity, newQuantity);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 从库存中移除物品
|
||||
public bool RemoveItem(string itemId, int quantity)
|
||||
{
|
||||
if (quantity <= 0) return false;
|
||||
|
||||
lock (inventoryLock)
|
||||
{
|
||||
if (!inventory.ContainsKey(itemId)) return false;
|
||||
|
||||
int oldQuantity = inventory[itemId].Quantity;
|
||||
if (oldQuantity < quantity) return false; // 库存不足
|
||||
|
||||
inventory[itemId].Quantity -= quantity;
|
||||
|
||||
int newQuantity = inventory[itemId].Quantity;
|
||||
GD.Print($"移除物品: {itemId} -{quantity} (剩余: {newQuantity})");
|
||||
|
||||
// 在锁外触发事件
|
||||
CallDeferred(nameof(TriggerInventoryChanged), itemId, oldQuantity, newQuantity);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 设置物品数量
|
||||
public void SetItemQuantity(string itemId, int quantity)
|
||||
{
|
||||
lock (inventoryLock)
|
||||
{
|
||||
int oldQuantity = GetItemQuantityUnsafe(itemId);
|
||||
|
||||
if (!inventory.ContainsKey(itemId))
|
||||
{
|
||||
inventory[itemId] = new InventoryItem(itemId, quantity);
|
||||
}
|
||||
else
|
||||
{
|
||||
inventory[itemId].Quantity = quantity;
|
||||
}
|
||||
|
||||
GD.Print($"设置物品数量: {itemId} = {quantity}");
|
||||
|
||||
// 在锁外触发事件
|
||||
CallDeferred(nameof(TriggerInventoryChanged), itemId, oldQuantity, quantity);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取物品数量(线程安全)
|
||||
public int GetItemQuantity(string itemId)
|
||||
{
|
||||
lock (inventoryLock)
|
||||
{
|
||||
return GetItemQuantityUnsafe(itemId);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取物品数量(非线程安全,内部使用)
|
||||
private int GetItemQuantityUnsafe(string itemId)
|
||||
{
|
||||
if (inventory.ContainsKey(itemId))
|
||||
{
|
||||
return inventory[itemId].Quantity;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 检查是否有足够的物品
|
||||
public bool HasEnoughItems(string itemId, int requiredQuantity)
|
||||
{
|
||||
return GetItemQuantity(itemId) >= requiredQuantity;
|
||||
}
|
||||
|
||||
// 检查是否有足够的材料(用于配方检查)
|
||||
public bool HasEnoughMaterials(Dictionary<string, int> recipe)
|
||||
{
|
||||
if (recipe == null) return true;
|
||||
|
||||
lock (inventoryLock)
|
||||
{
|
||||
foreach (var requirement in recipe)
|
||||
{
|
||||
if (GetItemQuantityUnsafe(requirement.Key) < requirement.Value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 消耗材料(用于生产)
|
||||
public bool ConsumeMaterials(Dictionary<string, int> recipe)
|
||||
{
|
||||
if (recipe == null) return true;
|
||||
|
||||
lock (inventoryLock)
|
||||
{
|
||||
// 先检查是否有足够材料
|
||||
foreach (var requirement in recipe)
|
||||
{
|
||||
if (GetItemQuantityUnsafe(requirement.Key) < requirement.Value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 消耗材料
|
||||
foreach (var requirement in recipe)
|
||||
{
|
||||
int oldQuantity = GetItemQuantityUnsafe(requirement.Key);
|
||||
inventory[requirement.Key].Quantity -= requirement.Value;
|
||||
int newQuantity = inventory[requirement.Key].Quantity;
|
||||
|
||||
// 在锁外触发事件
|
||||
CallDeferred(nameof(TriggerInventoryChanged), requirement.Key, oldQuantity, newQuantity);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取所有库存物品
|
||||
public Dictionary<string, InventoryItem> GetAllInventory()
|
||||
{
|
||||
lock (inventoryLock)
|
||||
{
|
||||
var result = new Dictionary<string, InventoryItem>();
|
||||
foreach (var item in inventory)
|
||||
{
|
||||
result[item.Key] = new InventoryItem(item.Value.ItemId, item.Value.Quantity);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取有库存的物品(数量>0)
|
||||
public Dictionary<string, InventoryItem> GetAvailableItems()
|
||||
{
|
||||
lock (inventoryLock)
|
||||
{
|
||||
var result = new Dictionary<string, InventoryItem>();
|
||||
foreach (var item in inventory)
|
||||
{
|
||||
if (item.Value.Quantity > 0)
|
||||
{
|
||||
result[item.Key] = new InventoryItem(item.Value.ItemId, item.Value.Quantity);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取指定分类的库存物品
|
||||
public Dictionary<string, InventoryItem> GetInventoryByCategory(GameData.ItemCategory category)
|
||||
{
|
||||
lock (inventoryLock)
|
||||
{
|
||||
var result = new Dictionary<string, InventoryItem>();
|
||||
|
||||
foreach (var item in inventory)
|
||||
{
|
||||
var itemData = GameData.Instance?.GetItem(item.Key);
|
||||
if (itemData != null && itemData.Category == category)
|
||||
{
|
||||
result[item.Key] = new InventoryItem(item.Value.ItemId, item.Value.Quantity);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// 清空库存
|
||||
public void ClearInventory()
|
||||
{
|
||||
Dictionary<string, int> oldQuantities;
|
||||
|
||||
lock (inventoryLock)
|
||||
{
|
||||
oldQuantities = new Dictionary<string, int>();
|
||||
|
||||
foreach (var item in inventory)
|
||||
{
|
||||
oldQuantities[item.Key] = item.Value.Quantity;
|
||||
item.Value.Quantity = 0;
|
||||
}
|
||||
|
||||
GD.Print("清空所有库存");
|
||||
}
|
||||
|
||||
// 在锁外触发事件
|
||||
foreach (var item in oldQuantities)
|
||||
{
|
||||
if (item.Value > 0)
|
||||
{
|
||||
CallDeferred(nameof(TriggerInventoryChanged), item.Key, item.Value, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取库存总数量
|
||||
public int GetTotalItemCount()
|
||||
{
|
||||
lock (inventoryLock)
|
||||
{
|
||||
return inventory.Values.Sum(item => item.Quantity);
|
||||
}
|
||||
}
|
||||
|
||||
// 调试:打印所有库存
|
||||
public void PrintInventory()
|
||||
{
|
||||
lock (inventoryLock)
|
||||
{
|
||||
GD.Print("=== 当前库存 ===");
|
||||
foreach (var item in inventory)
|
||||
{
|
||||
if (item.Value.Quantity > 0)
|
||||
{
|
||||
var itemData = GameData.Instance?.GetItem(item.Key);
|
||||
string itemName = itemData?.Name ?? item.Key;
|
||||
GD.Print($"{itemName}: {item.Value.Quantity}");
|
||||
}
|
||||
}
|
||||
GD.Print("===============");
|
||||
}
|
||||
}
|
||||
|
||||
// 触发库存变化事件(在主线程中调用)
|
||||
private void TriggerInventoryChanged(string itemId, int oldQuantity, int newQuantity)
|
||||
{
|
||||
InventoryChanged?.Invoke(itemId, oldQuantity, newQuantity);
|
||||
}
|
||||
|
||||
// 清理单例
|
||||
public override void _ExitTree()
|
||||
{
|
||||
if (instance == this)
|
||||
{
|
||||
instance = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user