添加基础的生产线内容-不少bug

This commit is contained in:
2025-06-17 00:05:47 +08:00
parent 7a6cd423fc
commit 50dc434ed9
11 changed files with 1435 additions and 17 deletions

View File

@ -0,0 +1,267 @@
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<ProductionRecipeItem> Inputs { get; set; } = new List<ProductionRecipeItem>();
public List<ProductionRecipeItem> Outputs { get; set; } = new List<ProductionRecipeItem>();
}
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<ProductionRecipeItem> BuildingRequirements { get; set; } = new List<ProductionRecipeItem>();
public ProductionRecipe Recipe { get; set; } = new ProductionRecipe();
}
public class ProductionLineData
{
public List<ProductionLine> ProductionLines { get; set; } = new List<ProductionLine>();
}
// 活跃的产线实例
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<string, ProductionLine> productionLineMap = new Dictionary<string, ProductionLine>();
private Dictionary<string, List<ProductionLine>> categoryMap = new Dictionary<string, List<ProductionLine>>();
private Dictionary<string, ActiveProductionLine> activeProductionLines = new Dictionary<string, ActiveProductionLine>();
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<ProductionLineData>(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<ProductionLine>();
}
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<ProductionLine> GetAllProductionLines()
{
return productionLineData?.ProductionLines ?? new List<ProductionLine>();
}
public ProductionLine GetProductionLine(string lineId)
{
return productionLineMap.GetValueOrDefault(lineId);
}
public List<ProductionLine> GetProductionLinesByCategory(string category)
{
return categoryMap.GetValueOrDefault(category) ?? new List<ProductionLine>();
}
public List<string> GetAllCategories()
{
return new List<string>(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<string, ActiveProductionLine> GetAllActiveProductionLines()
{
return activeProductionLines;
}
public override void _ExitTree()
{
if (Instance == this)
{
Instance = null;
}
}
}

View File

@ -0,0 +1,177 @@
using Godot;
using System.Collections.Generic;
public partial class ProductionProcessor : Node
{
public static ProductionProcessor Instance { get; private set; }
public override void _Ready()
{
if (Instance == null)
{
Instance = this;
GD.Print("ProductionProcessor 初始化完成");
}
else
{
QueueFree();
}
}
public override void _Process(double delta)
{
ProcessAllProductionLines((float)delta);
}
private void ProcessAllProductionLines(float deltaTime)
{
var productionLineManager = ProductionLineManager.Instance;
if (productionLineManager == null) return;
var activeLines = productionLineManager.GetAllActiveProductionLines();
foreach (var kvp in activeLines)
{
var activeLine = kvp.Value;
if (!activeLine.IsActive || activeLine.BuildingCount <= 0) continue;
ProcessProductionLine(activeLine, deltaTime);
}
}
private void ProcessProductionLine(ProductionLineManager.ActiveProductionLine activeLine, float deltaTime)
{
var productionLine = ProductionLineManager.Instance?.GetProductionLine(activeLine.ProductionLineId);
if (productionLine == null) return;
// 更新生产时间
activeLine.RemainingTime -= deltaTime;
if (activeLine.RemainingTime <= 0)
{
// 检查是否有足够的原料
if (CheckInputMaterials(productionLine, activeLine.BuildingCount))
{
// 消耗原料
ConsumeInputMaterials(productionLine, activeLine.BuildingCount);
// 生产产品
ProduceOutputItems(productionLine, activeLine.BuildingCount);
// 重置生产时间
activeLine.RemainingTime = productionLine.ProductionTime;
GD.Print($"产线 {productionLine.Name} 完成一轮生产,{activeLine.BuildingCount} 个建筑同时运行");
}
else
{
// 原料不足,暂停生产
activeLine.RemainingTime = 0.1f; // 短暂等待后再检查
GD.Print($"产线 {productionLine.Name} 原料不足,暂停生产");
}
}
}
private bool CheckInputMaterials(ProductionLineManager.ProductionLine productionLine, int buildingCount)
{
var inventoryManager = InventoryManager.Instance;
if (inventoryManager == null) return false;
// 检查所有输入材料
foreach (var input in productionLine.Recipe.Inputs)
{
int requiredQuantity = input.Quantity * buildingCount;
int availableQuantity = inventoryManager.GetItemQuantity(input.ItemId);
if (availableQuantity < requiredQuantity)
{
return false;
}
}
return true;
}
private void ConsumeInputMaterials(ProductionLineManager.ProductionLine productionLine, int buildingCount)
{
var inventoryManager = InventoryManager.Instance;
if (inventoryManager == null) return;
foreach (var input in productionLine.Recipe.Inputs)
{
int consumeQuantity = input.Quantity * buildingCount;
inventoryManager.RemoveItem(input.ItemId, consumeQuantity);
var itemData = GameData.Instance?.GetItem(input.ItemId);
string itemName = itemData?.Name ?? input.ItemId;
GD.Print($"消耗材料: {itemName} x{consumeQuantity}");
}
}
private void ProduceOutputItems(ProductionLineManager.ProductionLine productionLine, int buildingCount)
{
var inventoryManager = InventoryManager.Instance;
if (inventoryManager == null) return;
foreach (var output in productionLine.Recipe.Outputs)
{
int produceQuantity = output.Quantity * buildingCount;
inventoryManager.AddItem(output.ItemId, produceQuantity);
var itemData = GameData.Instance?.GetItem(output.ItemId);
string itemName = itemData?.Name ?? output.ItemId;
GD.Print($"生产物品: {itemName} x{produceQuantity}");
}
}
// 公共方法:获取产线当前状态信息
public ProductionLineStatus GetProductionLineStatus(string productionLineId)
{
var activeLine = ProductionLineManager.Instance?.GetActiveProductionLine(productionLineId);
var productionLine = ProductionLineManager.Instance?.GetProductionLine(productionLineId);
if (activeLine == null || productionLine == null)
{
return new ProductionLineStatus
{
IsActive = false,
Progress = 0,
ProductionRate = 0,
PowerConsumption = 0,
BuildingCount = 0
};
}
float progress = 0;
if (activeLine.IsActive && productionLine.ProductionTime > 0)
{
progress = 1.0f - (activeLine.RemainingTime / productionLine.ProductionTime);
}
return new ProductionLineStatus
{
IsActive = activeLine.IsActive,
Progress = Mathf.Clamp(progress, 0.0f, 1.0f),
ProductionRate = activeLine.ProductionRate,
PowerConsumption = activeLine.TotalPowerConsumption,
BuildingCount = activeLine.BuildingCount
};
}
public class ProductionLineStatus
{
public bool IsActive { get; set; }
public float Progress { get; set; } // 0-1的进度
public float ProductionRate { get; set; } // 每秒产出率
public int PowerConsumption { get; set; } // 功耗
public int BuildingCount { get; set; } // 建筑数量
}
public override void _ExitTree()
{
if (Instance == this)
{
Instance = null;
}
}
}