using Godot; using System.Collections.Generic; using System.Text.Json; public partial class ProductionLineManager : Node { public static ProductionLineManager Instance { get; private set; } public class ProductionRecipeItem { public string ItemId { get; set; } public int Quantity { get; set; } } public class ProductionRecipe { public List Inputs { get; set; } = new List(); public List Outputs { get; set; } = new List(); } public class ProductionLine { public string Id { get; set; } public string Name { get; set; } public string Category { get; set; } public string Description { get; set; } public float ProductionTime { get; set; } public int PowerConsumption { get; set; } public List BuildingRequirements { get; set; } = new List(); public ProductionRecipe Recipe { get; set; } = new ProductionRecipe(); } public class ProductionLineData { public List ProductionLines { get; set; } = new List(); } // 活跃的产线实例 public class ActiveProductionLine { public string ProductionLineId { get; set; } public int BuildingCount { get; set; } = 0; // 建筑数量 public float RemainingTime { get; set; } = 0; // 当前循环剩余时间 public bool IsActive { get; set; } = false; // 是否激活 public float ProductionRate { get; set; } = 0; // 每秒产出率 public int TotalPowerConsumption { get; set; } = 0; // 总功耗 } private ProductionLineData productionLineData; private Dictionary productionLineMap = new Dictionary(); private Dictionary> categoryMap = new Dictionary>(); private Dictionary activeProductionLines = new Dictionary(); public override void _Ready() { if (Instance == null) { Instance = this; LoadProductionLines(); } else { QueueFree(); } } private void LoadProductionLines() { string configPath = "res://data/config/production_lines.json"; if (!FileAccess.FileExists(configPath)) { GD.PrintErr($"自动产线配置文件不存在: {configPath}"); return; } using var file = FileAccess.Open(configPath, FileAccess.ModeFlags.Read); if (file == null) { GD.PrintErr($"无法打开自动产线配置文件: {configPath}"); return; } string jsonContent = file.GetAsText(); try { var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; productionLineData = JsonSerializer.Deserialize(jsonContent, options); if (productionLineData?.ProductionLines != null) { // 构建产线映射 foreach (var line in productionLineData.ProductionLines) { productionLineMap[line.Id] = line; // 按分类分组 if (!categoryMap.ContainsKey(line.Category)) { categoryMap[line.Category] = new List(); } categoryMap[line.Category].Add(line); GD.Print($"加载自动产线: {line.Id} - {line.Name} ({line.Category})"); } GD.Print($"成功加载 {productionLineData.ProductionLines.Count} 个自动产线"); } } catch (JsonException e) { GD.PrintErr($"解析自动产线配置文件失败: {e.Message}"); } } public List GetAllProductionLines() { return productionLineData?.ProductionLines ?? new List(); } public ProductionLine GetProductionLine(string lineId) { return productionLineMap.GetValueOrDefault(lineId); } public List GetProductionLinesByCategory(string category) { return categoryMap.GetValueOrDefault(category) ?? new List(); } public List GetAllCategories() { return new List(categoryMap.Keys); } // 建筑管理 public void AddBuilding(string productionLineId, int count = 1) { var productionLine = GetProductionLine(productionLineId); if (productionLine == null) { GD.PrintErr($"找不到产线: {productionLineId}"); return; } // 检查建筑需求 if (productionLine.BuildingRequirements == null || productionLine.BuildingRequirements.Count == 0) { GD.PrintErr($"产线 {productionLine.Name} 没有定义建筑需求"); return; } // 检查是否有足够的建筑材料 var inventoryManager = InventoryManager.Instance; if (inventoryManager == null) { GD.PrintErr("InventoryManager实例为null"); return; } // 验证所有建筑需求 foreach (var requirement in productionLine.BuildingRequirements) { int available = inventoryManager.GetItemQuantity(requirement.ItemId); int needed = requirement.Quantity * count; if (available < needed) { var itemData = GameData.Instance?.GetItem(requirement.ItemId); string itemName = itemData?.Name ?? requirement.ItemId; GD.Print($"建筑材料不足,需要 {needed} 个 {itemName},当前只有 {available} 个"); return; } } // 扣除建筑材料 foreach (var requirement in productionLine.BuildingRequirements) { int consumeAmount = requirement.Quantity * count; inventoryManager.RemoveItem(requirement.ItemId, consumeAmount); } // 添加到活跃产线 if (!activeProductionLines.ContainsKey(productionLineId)) { activeProductionLines[productionLineId] = new ActiveProductionLine { ProductionLineId = productionLineId }; } var activeLine = activeProductionLines[productionLineId]; activeLine.BuildingCount += count; activeLine.IsActive = true; activeLine.ProductionRate = activeLine.BuildingCount / productionLine.ProductionTime; // 每秒产出率 activeLine.TotalPowerConsumption = activeLine.BuildingCount * productionLine.PowerConsumption; GD.Print($"成功添加 {count} 个设备到产线 {productionLine.Name}"); GD.Print($"当前产线状态: {activeLine.BuildingCount} 个建筑, 产出率: {activeLine.ProductionRate:F2}/s, 功耗: {activeLine.TotalPowerConsumption}W"); } public void RemoveBuilding(string productionLineId, int count = 1) { if (!activeProductionLines.ContainsKey(productionLineId)) { GD.Print($"产线 {productionLineId} 没有建筑可移除"); return; } var activeLine = activeProductionLines[productionLineId]; var productionLine = GetProductionLine(productionLineId); count = Mathf.Min(count, activeLine.BuildingCount); if (count <= 0) return; activeLine.BuildingCount -= count; if (activeLine.BuildingCount <= 0) { activeLine.IsActive = false; activeLine.ProductionRate = 0; activeLine.TotalPowerConsumption = 0; } else { activeLine.ProductionRate = activeLine.BuildingCount / productionLine.ProductionTime; activeLine.TotalPowerConsumption = activeLine.BuildingCount * productionLine.PowerConsumption; } // 归还建筑材料到库存 var inventoryManager = InventoryManager.Instance; if (inventoryManager != null && productionLine.BuildingRequirements != null) { foreach (var requirement in productionLine.BuildingRequirements) { int returnAmount = requirement.Quantity * count; inventoryManager.AddItem(requirement.ItemId, returnAmount); } } GD.Print($"移除 {count} 个设备从产线 {productionLine.Name}"); GD.Print($"当前产线状态: {activeLine.BuildingCount} 个建筑, 产出率: {activeLine.ProductionRate:F2}/s, 功耗: {activeLine.TotalPowerConsumption}W"); } public ActiveProductionLine GetActiveProductionLine(string productionLineId) { return activeProductionLines.GetValueOrDefault(productionLineId); } public Dictionary GetAllActiveProductionLines() { return activeProductionLines; } public override void _ExitTree() { if (Instance == this) { Instance = null; } } }