using Godot; using System.Collections.Generic; public partial class CraftingQueueManager : Panel { public class CraftingQueueItem { public string RecipeId { get; set; } public int Quantity { get; set; } = 1; public float RemainingTime { get; set; } public float TotalTime { get; set; } public bool IsActive { get; set; } } private const int MAX_QUEUE_SIZE = 8; private List craftingQueue = new List(); private List slotPanels = new List(); public override void _Ready() { GD.Print("CraftingQueueManager _Ready 开始"); // 获取所有槽位面板 var queueContainer = GetNode("MarginContainer/VBoxContainer/QueueContainer"); for (int i = 1; i <= MAX_QUEUE_SIZE; i++) { var slot = queueContainer.GetNode($"Slot{i}"); slotPanels.Add(slot); } // 初始化队列显示 UpdateQueueDisplay(); GD.Print("CraftingQueueManager 初始化完成"); } public override void _Process(double delta) { ProcessCrafting((float)delta); } private void ProcessCrafting(float deltaTime) { if (craftingQueue.Count == 0) return; // 处理第一个(当前正在制作的)物品 var currentItem = craftingQueue[0]; if (!currentItem.IsActive) { // 开始制作 currentItem.IsActive = true; GD.Print($"开始制作: {currentItem.RecipeId}"); // 重新更新显示以确保进度条正确初始化 UpdateQueueDisplay(); return; // 这一帧先不处理时间,让UI先更新 } currentItem.RemainingTime -= deltaTime; if (currentItem.RemainingTime <= 0) { // 制作完成 CompleteCrafting(currentItem); craftingQueue.RemoveAt(0); UpdateQueueDisplay(); } else { // 更新进度显示 float progress = 1.0f - (currentItem.RemainingTime / currentItem.TotalTime); UpdateSlotProgress(0, progress); } } private void CompleteCrafting(CraftingQueueItem item) { var recipe = CraftingRecipeManager.Instance?.GetRecipe(item.RecipeId); if (recipe == null || InventoryManager.Instance == null) { GD.PrintErr($"无法完成制作: {item.RecipeId}"); return; } // 添加产品到库存(数量 = 配方产出数量 × 批量数量) int totalOutputQuantity = recipe.OutputQuantity * item.Quantity; InventoryManager.Instance.AddItem(recipe.OutputItem, totalOutputQuantity); GD.Print($"制作完成: {recipe.OutputItem} x{totalOutputQuantity} (批量: {item.Quantity})"); } public bool AddToQueue(string recipeId, int quantity = 1) { if (craftingQueue.Count >= MAX_QUEUE_SIZE) { GD.Print("合成队列已满"); return false; } var recipe = CraftingRecipeManager.Instance?.GetRecipe(recipeId); if (recipe == null) { GD.PrintErr($"找不到配方: {recipeId}"); return false; } // 检查是否有足够的材料制作指定数量 foreach (var ingredient in recipe.Ingredients) { int requiredQuantity = ingredient.Quantity * quantity; if (InventoryManager.Instance.GetItemQuantity(ingredient.ItemId) < requiredQuantity) { GD.Print($"材料不足,无法制作 {quantity} 个: {recipeId}"); return false; } } // 扣除材料(数量 = 配方需求 × 批量数量) foreach (var ingredient in recipe.Ingredients) { int totalRequired = ingredient.Quantity * quantity; InventoryManager.Instance.RemoveItem(ingredient.ItemId, totalRequired); GD.Print($"扣除材料: {ingredient.ItemId} x{totalRequired} (批量: {quantity})"); } // 计算总制作时间(时间 = 基础时间 × 数量) float totalCraftingTime = recipe.CraftingTime * quantity; var queueItem = new CraftingQueueItem { RecipeId = recipeId, Quantity = quantity, RemainingTime = totalCraftingTime, TotalTime = totalCraftingTime, IsActive = false }; craftingQueue.Add(queueItem); UpdateQueueDisplay(); GD.Print($"添加到合成队列: {recipeId} x{quantity},总时间: {totalCraftingTime}s,已扣除材料"); return true; } private void UpdateQueueDisplay() { // 清空所有槽位 for (int i = 0; i < slotPanels.Count; i++) { ClearSlot(i); } // 显示队列中的物品 for (int i = 0; i < craftingQueue.Count && i < slotPanels.Count; i++) { var queueItem = craftingQueue[i]; var recipe = CraftingRecipeManager.Instance?.GetRecipe(queueItem.RecipeId); if (recipe != null) { UpdateSlotDisplay(i, recipe, queueItem); } } } private void UpdateSlotDisplay(int slotIndex, CraftingRecipeManager.CraftingRecipe recipe, CraftingQueueItem queueItem) { var slot = slotPanels[slotIndex]; // 立即清除现有的子节点,而不是使用QueueFree var childrenToRemove = new List(); foreach (Node child in slot.GetChildren()) { childrenToRemove.Add(child); } foreach (Node child in childrenToRemove) { slot.RemoveChild(child); child.QueueFree(); } // 创建背景层(灰色) var backgroundRect = new ColorRect(); backgroundRect.Name = "Background"; backgroundRect.Color = new Color(0.3f, 0.3f, 0.3f, 1.0f); backgroundRect.AnchorLeft = 0.0f; backgroundRect.AnchorTop = 0.0f; backgroundRect.AnchorRight = 1.0f; backgroundRect.AnchorBottom = 1.0f; slot.AddChild(backgroundRect); // 创建图标显示层 var iconTexture = new TextureRect(); iconTexture.Name = "ProductIcon"; iconTexture.ExpandMode = TextureRect.ExpandModeEnum.FitWidthProportional; iconTexture.StretchMode = TextureRect.StretchModeEnum.KeepAspectCentered; iconTexture.AnchorLeft = 0.1f; iconTexture.AnchorTop = 0.1f; iconTexture.AnchorRight = 0.9f; iconTexture.AnchorBottom = 0.9f; // 获取产物的图标 var outputItemData = GameData.Instance?.GetItem(recipe.OutputItem); if (outputItemData != null && !string.IsNullOrEmpty(outputItemData.IconPath)) { // 尝试加载物品图标 if (FileAccess.FileExists(outputItemData.IconPath)) { var texture = GD.Load(outputItemData.IconPath); if (texture != null) { iconTexture.Texture = texture; GD.Print($"槽位{slotIndex}加载产物图标: {outputItemData.IconPath}"); } else { // 使用默认图标 LoadDefaultIcon(iconTexture); } } else { // 使用默认图标 LoadDefaultIcon(iconTexture); } } else { // 使用默认图标 LoadDefaultIcon(iconTexture); } slot.AddChild(iconTexture); // 创建进度层(白色半透明,覆盖在图标上面) var progressRect = new ColorRect(); progressRect.Name = "Progress"; progressRect.AnchorLeft = 0.0f; progressRect.AnchorRight = 1.0f; progressRect.AnchorBottom = 1.0f; progressRect.Color = new Color(1.0f, 1.0f, 1.0f, 0.3f); // 白色,透明度0.3 // 根据是否激活设置初始进度 if (queueItem.IsActive) { float progress = 1.0f - (queueItem.RemainingTime / queueItem.TotalTime); progressRect.AnchorTop = 1.0f - progress; // 从下往上填充 GD.Print($"槽位{slotIndex}初始化进度条,进度: {progress:F2}"); } else { progressRect.AnchorTop = 1.0f; // 等待状态,无进度显示 } slot.AddChild(progressRect); // 添加数量标签(如果数量大于1) if (queueItem.Quantity > 1) { var quantityLabel = new Label(); quantityLabel.Name = "QuantityLabel"; quantityLabel.Text = queueItem.Quantity.ToString(); quantityLabel.AnchorLeft = 0.6f; quantityLabel.AnchorTop = 0.6f; quantityLabel.AnchorRight = 1.0f; quantityLabel.AnchorBottom = 1.0f; quantityLabel.HorizontalAlignment = HorizontalAlignment.Center; quantityLabel.VerticalAlignment = VerticalAlignment.Center; quantityLabel.AddThemeStyleboxOverride("normal", new StyleBoxFlat()); var styleBox = quantityLabel.GetThemeStylebox("normal") as StyleBoxFlat; if (styleBox != null) { styleBox.BgColor = new Color(0.2f, 0.2f, 0.2f, 0.8f); // 半透明黑色背景 styleBox.CornerRadiusTopLeft = 3; styleBox.CornerRadiusTopRight = 3; styleBox.CornerRadiusBottomLeft = 3; styleBox.CornerRadiusBottomRight = 3; } quantityLabel.AddThemeColorOverride("font_color", new Color(1.0f, 1.0f, 1.0f, 1.0f)); // 白色文字 quantityLabel.AddThemeFontSizeOverride("font_size", 8); slot.AddChild(quantityLabel); } // 重置槽位颜色为默认 slot.Modulate = new Color(1.0f, 1.0f, 1.0f, 1.0f); } private void LoadDefaultIcon(TextureRect iconTexture) { var defaultIcon = GD.Load("res://assets/textures/icon.svg"); if (defaultIcon != null) { iconTexture.Texture = defaultIcon; GD.Print("使用默认图标 icon.svg"); } else { GD.PrintErr("无法加载默认图标 icon.svg"); } } private void UpdateSlotProgress(int slotIndex, float progress) { if (slotIndex >= slotPanels.Count) { GD.PrintErr($"UpdateSlotProgress: 无效的槽位索引 {slotIndex}"); return; } var slot = slotPanels[slotIndex]; if (slot == null || !IsInstanceValid(slot)) { GD.PrintErr($"UpdateSlotProgress: 槽位{slotIndex}无效"); return; } // 安全获取Progress节点 ColorRect progressRect = null; try { if (slot.HasNode("Progress")) { progressRect = slot.GetNode("Progress"); } else { GD.PrintErr($"UpdateSlotProgress: 槽位{slotIndex}没有Progress节点"); return; } } catch (System.Exception e) { GD.PrintErr($"UpdateSlotProgress: 获取Progress节点失败: {e.Message}"); return; } if (progressRect != null && IsInstanceValid(progressRect)) { // 从下往上填充:progress为0时AnchorTop为1.0,progress为1时AnchorTop为0.0 float anchorTop = 1.0f - progress; progressRect.AnchorTop = anchorTop; // GD.Print($"更新槽位{slotIndex}进度: {progress:F2}, AnchorTop: {anchorTop:F2}"); } else { GD.PrintErr($"UpdateSlotProgress: 槽位{slotIndex}的Progress节点无效"); } } private void ClearSlot(int slotIndex) { var slot = slotPanels[slotIndex]; // 立即清除子节点 var childrenToRemove = new List(); foreach (Node child in slot.GetChildren()) { childrenToRemove.Add(child); } foreach (Node child in childrenToRemove) { slot.RemoveChild(child); child.QueueFree(); } // 为空槽位添加灰色背景 var backgroundRect = new ColorRect(); backgroundRect.Name = "Background"; backgroundRect.Color = new Color(0.2f, 0.2f, 0.2f, 1.0f); // 更深的灰色表示空槽位 backgroundRect.AnchorLeft = 0.0f; backgroundRect.AnchorTop = 0.0f; backgroundRect.AnchorRight = 1.0f; backgroundRect.AnchorBottom = 1.0f; slot.AddChild(backgroundRect); // 重置槽位颜色 slot.Modulate = new Color(1.0f, 1.0f, 1.0f, 1.0f); } // 公共方法,供外部调用添加铁块制作 public void StartIronIngotCrafting() { AddToQueue("iron_ingot_smelting"); } }