Files
Godot-test/scripts/inventory/InventoryManager.cs

370 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);
AddItem("magnet", 8); // 添加磁铁,用于合成磁线圈
AddItem("gear", 6); // 添加齿轮,用于合成钻机
}
// 添加物品到库存
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;
}
}
}