Files
WulaFallenEmpireRW/Source/WulaFallenEmpire/GlobalWorkTable/JobDriver_GlobalWorkTable.cs
2025-11-22 17:42:47 +08:00

119 lines
4.6 KiB
C#

using RimWorld;
using System.Collections.Generic;
using System.Linq;
using Verse;
using Verse.AI;
namespace WulaFallenEmpire
{
public class JobDriver_GlobalWorkTable : JobDriver
{
private const TargetIndex TableIndex = TargetIndex.A;
private const TargetIndex IngredientIndex = TargetIndex.B;
private const TargetIndex IngredientPlaceCellIndex = TargetIndex.C;
protected Building_GlobalWorkTable Table => (Building_GlobalWorkTable)job.GetTarget(TableIndex).Thing;
public override bool TryMakePreToilReservations(bool errorOnFailed)
{
if (!pawn.Reserve(Table, job, 1, -1, null, errorOnFailed))
return false;
pawn.ReserveAsManyAsPossible(job.GetTargetQueue(IngredientIndex), job);
return true;
}
protected override IEnumerable<Toil> MakeNewToils()
{
this.FailOnDestroyedOrNull(TableIndex);
this.FailOnForbidden(TableIndex);
// 1. 前往工作台
yield return Toils_Goto.GotoThing(TableIndex, PathEndMode.InteractionCell);
// 2. 收集材料 (使用原版 JobDriver_DoBill 的逻辑)
// 参数: ingredientInd, billGiverInd, ingredientPlaceCellInd, subtractNumTakenFromJobCount, failIfStackCountLessThanJobCount, placeInBillGiver
foreach (Toil toil in JobDriver_DoBill.CollectIngredientsToils(IngredientIndex, TableIndex, IngredientPlaceCellIndex, false, true, true))
{
yield return toil;
}
// 3. 检查并触发上传
yield return new Toil
{
initAction = delegate
{
CheckAndUpload();
},
defaultCompleteMode = ToilCompleteMode.Instant
};
}
private void CheckAndUpload()
{
var table = Table;
var globalStorage = Find.World.GetComponent<GlobalStorageWorldComponent>();
// 找到当前正在进行的订单
var order = table.globalOrderStack.orders.FirstOrDefault(o => o.state == GlobalProductionOrder.ProductionState.Gathering && !o.paused);
if (order == null) return;
// 检查是否满足需求
var costList = order.GetProductCostList();
bool allSatisfied = true;
foreach (var kvp in costList)
{
int needed = kvp.Value;
int inCloud = globalStorage.GetInputStorageCount(kvp.Key);
int inContainer = table.innerContainer.TotalStackCountOfDef(kvp.Key);
if (inCloud + inContainer < needed)
{
allSatisfied = false;
break;
}
}
if (allSatisfied)
{
// 1. 消耗容器中的材料并上传到云端
foreach (var kvp in costList)
{
int needed = kvp.Value;
int inCloud = globalStorage.GetInputStorageCount(kvp.Key);
int missingInCloud = needed - inCloud;
if (missingInCloud > 0)
{
int toTake = missingInCloud;
while (toTake > 0)
{
Thing t = table.innerContainer.FirstOrDefault(x => x.def == kvp.Key);
if (t == null) break;
int num = UnityEngine.Mathf.Min(t.stackCount, toTake);
t.SplitOff(num).Destroy(); // 销毁实体
globalStorage.AddToInputStorage(kvp.Key, num); // 添加虚拟库存
toTake -= num;
}
}
}
// 2. 立即尝试扣除资源并开始生产
// 这会从云端扣除刚刚上传的资源,防止其他订单抢占
if (order.TryDeductResources())
{
order.state = GlobalProductionOrder.ProductionState.Producing;
order.progress = 0f;
Messages.Message("WULA_OrderStarted".Translate(order.Label), table, MessageTypeDefOf.PositiveEvent);
}
else
{
// 理论上不应该发生,因为前面检查了 allSatisfied
Log.Error($"[WULA] Failed to deduct resources for {order.Label} immediately after upload.");
}
}
}
}
}