From 98c30201c5d3ca1147f6d2656895d0f600316187 Mon Sep 17 00:00:00 2001 From: "ProjectKoi-Kalo\\Kalo" Date: Sun, 14 Dec 2025 11:52:17 +0800 Subject: [PATCH] zc --- .../GlobalWorkTable/GlobalProductionOrder.cs | 46 +++++++++++++++---- .../GlobalProductionOrderStack.cs | 40 ++++++++++------ .../WorkGiver_GlobalWorkTable.cs | 19 ++++---- 3 files changed, 74 insertions(+), 31 deletions(-) diff --git a/Source/WulaFallenEmpire/GlobalWorkTable/GlobalProductionOrder.cs b/Source/WulaFallenEmpire/GlobalWorkTable/GlobalProductionOrder.cs index d26cdc5b..9c32cd2d 100644 --- a/Source/WulaFallenEmpire/GlobalWorkTable/GlobalProductionOrder.cs +++ b/Source/WulaFallenEmpire/GlobalWorkTable/GlobalProductionOrder.cs @@ -132,36 +132,62 @@ namespace WulaFallenEmpire var globalStorage = Find.World.GetComponent(); if (globalStorage == null) return false; - // 检查资源是否足够 - if (!HasEnoughResources()) return false; - - // 扣除资源 + // 扣除资源(需要处理扣除失败的情况,避免出现“扣料失败但仍返回 true”的无成本生产) var productCostList = GetProductCostList(); if (productCostList.Count > 0) { + Dictionary removed = new Dictionary(); + foreach (var kvp in productCostList) { - globalStorage.RemoveFromInputStorage(kvp.Key, kvp.Value); + if (kvp.Value <= 0) continue; + + if (!globalStorage.RemoveFromInputStorage(kvp.Key, kvp.Value)) + { + foreach (var r in removed) + { + globalStorage.AddToInputStorage(r.Key, r.Value); + } + return false; + } + + removed[kvp.Key] = kvp.Value; } - return true; + + return removed.Count > 0; } + List> removedIngredients = new List>(); foreach (var ingredient in recipe.ingredients) { + bool removedForThisIngredient = false; foreach (var thingDef in ingredient.filter.AllowedThingDefs) { int requiredCount = ingredient.CountRequiredOfFor(thingDef, recipe); int availableCount = globalStorage.GetInputStorageCount(thingDef); - if (availableCount >= requiredCount) + if (requiredCount > 0 && availableCount >= requiredCount) { - globalStorage.RemoveFromInputStorage(thingDef, requiredCount); - break; // 只扣除一种满足条件的材料 + if (globalStorage.RemoveFromInputStorage(thingDef, requiredCount)) + { + removedIngredients.Add(new KeyValuePair(thingDef, requiredCount)); + removedForThisIngredient = true; + break; // 只扣除一种满足条件的材料 + } } } + + if (!removedForThisIngredient) + { + foreach (var r in removedIngredients) + { + globalStorage.AddToInputStorage(r.Key, r.Value); + } + return false; + } } - return true; + return removedIngredients.Count > 0; } // 修复:GetIngredientsTooltip 方法,显示正确的成本信息 diff --git a/Source/WulaFallenEmpire/GlobalWorkTable/GlobalProductionOrderStack.cs b/Source/WulaFallenEmpire/GlobalWorkTable/GlobalProductionOrderStack.cs index 9bd2a158..20dc05e1 100644 --- a/Source/WulaFallenEmpire/GlobalWorkTable/GlobalProductionOrderStack.cs +++ b/Source/WulaFallenEmpire/GlobalWorkTable/GlobalProductionOrderStack.cs @@ -13,7 +13,7 @@ namespace WulaFallenEmpire // 修复:明确的工作量定义 private const float WorkPerSecond = 60f; // 每秒60工作量(标准RimWorld速度) private const float TicksPerSecond = 60f; - private const float WorkPerTick = WorkPerSecond / TicksPerSecond; // 每tick 1工作量 + private int lastProcessedTick = -1; public GlobalProductionOrderStack(Building_GlobalWorkTable table) { @@ -56,6 +56,13 @@ namespace WulaFallenEmpire public void ProcessOrders() { + int currentTick = Find.TickManager.TicksGame; + int deltaTicks = lastProcessedTick < 0 ? 1 : currentTick - lastProcessedTick; + if (deltaTicks <= 0) deltaTicks = 1; + lastProcessedTick = currentTick; + + float workThisStep = WorkPerSecond * (deltaTicks / TicksPerSecond); + // 修复:使用倒序遍历避免修改集合问题 for (int i = orders.Count - 1; i >= 0; i--) { @@ -70,7 +77,7 @@ namespace WulaFallenEmpire // 生产中 if (order.state == GlobalProductionOrder.ProductionState.Producing) { - ProcessProducingOrder(order, i); + ProcessProducingOrder(order, i, workThisStep); } else if (order.state == GlobalProductionOrder.ProductionState.Gathering && !order.paused) { @@ -79,7 +86,7 @@ namespace WulaFallenEmpire } } - private void ProcessProducingOrder(GlobalProductionOrder order, int index) + private void ProcessProducingOrder(GlobalProductionOrder order, int index, float workThisStep) { // 修复:使用正确的方法获取工作量 float workAmount = GetWorkAmountForOrder(order); @@ -93,8 +100,8 @@ namespace WulaFallenEmpire return; } - // 修复:正确计算进度增量 - float progressIncrement = WorkPerTick / workAmount; + // 修复:按两次 ProcessOrders 调用间隔的 tick 计算,避免调用频率变化导致生产速度偏差 + float progressIncrement = workThisStep / workAmount; // 修复:确保进度不会变成负数 float newProgress = Mathf.Max(0f, order.progress + progressIncrement); @@ -152,15 +159,22 @@ namespace WulaFallenEmpire private void ProcessWaitingOrder(GlobalProductionOrder order) { - // 检查是否应该开始生产 + // 注意:这里不能在不扣料的情况下把 Gathering 直接切到 Producing(会绕过 TryDeductResources) if (order.HasEnoughResources()) { - order.state = GlobalProductionOrder.ProductionState.Producing; - order.progress = 0f; - - if (Find.TickManager.TicksGame % 600 == 0) // 每10秒记录一次 + if (order.TryDeductResources()) { - Log.Message($"[INFO] Order {order.recipe.defName} started producing"); + order.state = GlobalProductionOrder.ProductionState.Producing; + order.progress = 0f; + + if (Find.TickManager.TicksGame % 600 == 0) // 每10秒记录一次 + { + Log.Message($"[INFO] Order {order.recipe.defName} started producing"); + } + } + else + { + Log.Warning($"[WULA] Order {order.recipe.defName} had enough resources but failed to deduct them; staying in Gathering."); } } else if (Find.TickManager.TicksGame % 1200 == 0) // 每20秒检查一次 @@ -185,7 +199,7 @@ namespace WulaFallenEmpire if (order.currentCount >= order.targetCount) { order.state = GlobalProductionOrder.ProductionState.Completed; - orders.RemoveAt(index); + Delete(order); // 同步 GlobalStorageWorldComponent.productionOrders Log.Message($"[COMPLETE] Order {order.recipe.defName} completed and removed"); } else @@ -225,7 +239,7 @@ namespace WulaFallenEmpire if (order.recipe == null) { Log.Warning($"Removing order with null recipe"); - orders.RemoveAt(i); + Delete(order); // 同步 GlobalStorageWorldComponent.productionOrders continue; } diff --git a/Source/WulaFallenEmpire/GlobalWorkTable/WorkGiver_GlobalWorkTable.cs b/Source/WulaFallenEmpire/GlobalWorkTable/WorkGiver_GlobalWorkTable.cs index df9eb8ca..26ee6e6a 100644 --- a/Source/WulaFallenEmpire/GlobalWorkTable/WorkGiver_GlobalWorkTable.cs +++ b/Source/WulaFallenEmpire/GlobalWorkTable/WorkGiver_GlobalWorkTable.cs @@ -126,6 +126,8 @@ namespace WulaFallenEmpire var totalRequired = order.GetProductCostList(); if (totalRequired.Count == 0) { + totalRequired = new Dictionary(); + // 处理配方原料 (Ingredients) - 简化处理,假设配方只使用固定材料 // 实际情况可能更复杂,需要处理过滤器 foreach (var ingredient in order.recipe.ingredients) @@ -133,19 +135,20 @@ namespace WulaFallenEmpire // 这里简化:只取第一个允许的物品作为需求 // 更好的做法是动态匹配,但这需要更复杂的逻辑 var def = ingredient.filter.AllowedThingDefs.FirstOrDefault(); - if (def != null) - { - int count = (int)ingredient.GetBaseCount(); - if (needed.ContainsKey(def)) needed[def] += count; - else needed[def] = count; - } + if (def == null) continue; + + int count = ingredient.CountRequiredOfFor(def, order.recipe); + if (count <= 0) continue; + + if (totalRequired.ContainsKey(def)) totalRequired[def] += count; + else totalRequired[def] = count; } } // 2. 减去云端已有的 foreach (var kvp in totalRequired) { - int cloudCount = storage.GetInputStorageCount(kvp.Key); + int cloudCount = storage?.GetInputStorageCount(kvp.Key) ?? 0; int remaining = kvp.Value - cloudCount; // 3. 减去工作台容器中已有的 @@ -161,4 +164,4 @@ namespace WulaFallenEmpire return needed; } } -} \ No newline at end of file +}