zc
This commit is contained in:
Binary file not shown.
BIN
1.6/1.6/Assemblies/WulaFallenEmpire.pdb
Normal file
BIN
1.6/1.6/Assemblies/WulaFallenEmpire.pdb
Normal file
Binary file not shown.
@@ -146,9 +146,7 @@ namespace WulaFallenEmpire
|
|||||||
|
|
||||||
int take = Mathf.Min(thing.stackCount, remaining);
|
int take = Mathf.Min(thing.stackCount, remaining);
|
||||||
Thing split = thing.SplitOff(take);
|
Thing split = thing.SplitOff(take);
|
||||||
split.Destroy(DestroyMode.Vanish);
|
storage.AddToInputStorage(split);
|
||||||
|
|
||||||
storage.AddToInputStorage(def, take);
|
|
||||||
|
|
||||||
uploaded += take;
|
uploaded += take;
|
||||||
remaining -= take;
|
remaining -= take;
|
||||||
@@ -181,9 +179,7 @@ namespace WulaFallenEmpire
|
|||||||
|
|
||||||
int take = Mathf.Min(t.stackCount, remaining);
|
int take = Mathf.Min(t.stackCount, remaining);
|
||||||
Thing split = t.SplitOff(take);
|
Thing split = t.SplitOff(take);
|
||||||
split.Destroy(DestroyMode.Vanish);
|
storage.AddToInputStorage(split);
|
||||||
|
|
||||||
storage.AddToInputStorage(def, take);
|
|
||||||
uploaded += take;
|
uploaded += take;
|
||||||
remaining -= take;
|
remaining -= take;
|
||||||
}
|
}
|
||||||
@@ -223,7 +219,7 @@ namespace WulaFallenEmpire
|
|||||||
action = OpenGlobalStorageTransferDialog,
|
action = OpenGlobalStorageTransferDialog,
|
||||||
defaultLabel = "WULA_AccessGlobalStorage".Translate(),
|
defaultLabel = "WULA_AccessGlobalStorage".Translate(),
|
||||||
defaultDesc = "WULA_AccessGlobalStorageDesc".Translate(),
|
defaultDesc = "WULA_AccessGlobalStorageDesc".Translate(),
|
||||||
icon = ContentFinder<Texture2D>.Get("UI/Commands/Trade", true),
|
icon = ContentFinder<Texture2D>.Get("UI/Commands/Trade", false) ?? TexButton.Search,
|
||||||
};
|
};
|
||||||
|
|
||||||
// 白银转移按钮 - 检查输入端是否有白银
|
// 白银转移按钮 - 检查输入端是否有白银
|
||||||
@@ -241,7 +237,7 @@ namespace WulaFallenEmpire
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
// 原有的空投按钮逻辑保持不变
|
// 原有的空投按钮逻辑保持不变
|
||||||
bool hasOutputItems = globalStorage != null && globalStorage.outputStorage.Any(kvp => kvp.Value > 0);
|
bool hasOutputItems = globalStorage != null && globalStorage.GetOutputStorageTotalCount() > 0;
|
||||||
bool hasFactoryFlyOver = HasFactoryFacilityFlyOver();
|
bool hasFactoryFlyOver = HasFactoryFacilityFlyOver();
|
||||||
if (hasOutputItems && hasFactoryFlyOver)
|
if (hasOutputItems && hasFactoryFlyOver)
|
||||||
{
|
{
|
||||||
@@ -320,11 +316,8 @@ namespace WulaFallenEmpire
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 从输入端移除白银
|
if (TryMoveBetweenStorages(globalStorage.inputContainer, globalStorage.outputContainer, ThingDefOf.Silver, silverAmount))
|
||||||
if (globalStorage.RemoveFromInputStorage(ThingDefOf.Silver, silverAmount))
|
|
||||||
{
|
{
|
||||||
// 添加到输出端
|
|
||||||
globalStorage.AddToOutputStorage(ThingDefOf.Silver, silverAmount);
|
|
||||||
|
|
||||||
// 显示成功消息
|
// 显示成功消息
|
||||||
Messages.Message("WULA_SilverTransferred".Translate(silverAmount), MessageTypeDefOf.PositiveEvent);
|
Messages.Message("WULA_SilverTransferred".Translate(silverAmount), MessageTypeDefOf.PositiveEvent);
|
||||||
@@ -344,6 +337,28 @@ namespace WulaFallenEmpire
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool TryMoveBetweenStorages(ThingOwner<Thing> from, ThingOwner<Thing> to, ThingDef def, int count)
|
||||||
|
{
|
||||||
|
if (from == null || to == null || def == null || count <= 0) return false;
|
||||||
|
|
||||||
|
int available = from.Where(t => t != null && t.def == def).Sum(t => t.stackCount);
|
||||||
|
if (available < count) return false;
|
||||||
|
|
||||||
|
int remaining = count;
|
||||||
|
for (int i = from.Count - 1; i >= 0 && remaining > 0; i--)
|
||||||
|
{
|
||||||
|
Thing t = from[i];
|
||||||
|
if (t == null || t.def != def) continue;
|
||||||
|
|
||||||
|
int take = Mathf.Min(t.stackCount, remaining);
|
||||||
|
Thing split = t.SplitOff(take); // count>=stackCount 时会从 from 中移除该 Thing
|
||||||
|
to.TryAdd(split, true);
|
||||||
|
remaining -= take;
|
||||||
|
}
|
||||||
|
|
||||||
|
return remaining <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
// 新增:检查是否有拥有FactoryFacility设施的飞行器
|
// 新增:检查是否有拥有FactoryFacility设施的飞行器
|
||||||
private bool HasFactoryFacilityFlyOver()
|
private bool HasFactoryFacilityFlyOver()
|
||||||
{
|
{
|
||||||
@@ -397,7 +412,7 @@ namespace WulaFallenEmpire
|
|||||||
{
|
{
|
||||||
// 检查是否有输出物品
|
// 检查是否有输出物品
|
||||||
var globalStorage = Find.World.GetComponent<GlobalStorageWorldComponent>();
|
var globalStorage = Find.World.GetComponent<GlobalStorageWorldComponent>();
|
||||||
if (globalStorage == null || !globalStorage.outputStorage.Any(kvp => kvp.Value > 0))
|
if (globalStorage == null || globalStorage.GetOutputStorageTotalCount() <= 0)
|
||||||
{
|
{
|
||||||
Messages.Message("WULA_NoProductsToAirdrop".Translate(), MessageTypeDefOf.RejectInput);
|
Messages.Message("WULA_NoProductsToAirdrop".Translate(), MessageTypeDefOf.RejectInput);
|
||||||
return;
|
return;
|
||||||
@@ -550,85 +565,17 @@ namespace WulaFallenEmpire
|
|||||||
{
|
{
|
||||||
podContents.Add(new List<Thing>());
|
podContents.Add(new List<Thing>());
|
||||||
}
|
}
|
||||||
// 获取所有输出物品并转换为Thing列表
|
|
||||||
List<Thing> allItems = new List<Thing>();
|
List<Thing> allItems = new List<Thing>();
|
||||||
|
for (int i = storage.outputContainer.Count - 1; i >= 0; i--)
|
||||||
// 首先处理机械体,因为需要特殊处理
|
|
||||||
foreach (var kvp in storage.outputStorage.ToList())
|
|
||||||
{
|
{
|
||||||
if (kvp.Value <= 0) continue;
|
Thing t = storage.outputContainer[i];
|
||||||
ThingDef thingDef = kvp.Key;
|
if (t == null) continue;
|
||||||
int remainingCount = kvp.Value;
|
|
||||||
// 如果是Pawn,需要特殊处理
|
|
||||||
if (thingDef.race != null)
|
|
||||||
{
|
|
||||||
// 对于Pawn,每个单独生成
|
|
||||||
for (int i = 0; i < remainingCount; i++)
|
|
||||||
{
|
|
||||||
PawnKindDef randomPawnKind = GetRandomPawnKindForType(thingDef);
|
|
||||||
if (randomPawnKind != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Pawn pawn = PawnGenerator.GeneratePawn(randomPawnKind, Faction.OfPlayer);
|
|
||||||
// 确保Pawn处于活跃状态
|
|
||||||
if (pawn != null)
|
|
||||||
{
|
|
||||||
// 设置Pawn为可用的状态
|
|
||||||
pawn.health.Reset();
|
|
||||||
pawn.drafter = new Pawn_DraftController(pawn);
|
|
||||||
|
|
||||||
allItems.Add(pawn);
|
storage.outputContainer.Remove(t);
|
||||||
}
|
allItems.Add(t);
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.Error("[Airdrop] Generated pawn is null");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (System.Exception ex)
|
|
||||||
{
|
|
||||||
Log.Error($"[Airdrop] Error generating pawn: {ex}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.Error($"[Airdrop] Could not find suitable PawnKindDef for {thingDef.defName}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 立即从存储中移除已处理的机械体
|
|
||||||
storage.RemoveFromOutputStorage(thingDef, remainingCount);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// 然后处理普通物品
|
|
||||||
foreach (var kvp in storage.outputStorage.ToList())
|
|
||||||
{
|
|
||||||
if (kvp.Value <= 0) continue;
|
|
||||||
ThingDef thingDef = kvp.Key;
|
|
||||||
int remainingCount = kvp.Value;
|
|
||||||
// 跳过已经处理的机械体
|
|
||||||
if (thingDef.race != null) continue;
|
|
||||||
Log.Message($"[Airdrop] Processing {remainingCount} items of type {thingDef.defName}");
|
|
||||||
// 对于普通物品,按照堆叠限制分割
|
|
||||||
while (remainingCount > 0)
|
|
||||||
{
|
|
||||||
int stackSize = Mathf.Min(remainingCount, thingDef.stackLimit);
|
|
||||||
Thing thing = CreateThingWithMaterial(thingDef, stackSize);
|
|
||||||
if (thing != null)
|
|
||||||
{
|
|
||||||
allItems.Add(thing);
|
|
||||||
remainingCount -= stackSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.Error($"[Airdrop] Failed to create thing: {thingDef.defName}");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从存储中移除已处理的物品
|
|
||||||
storage.RemoveFromOutputStorage(thingDef, kvp.Value);
|
|
||||||
}
|
|
||||||
if (allItems.Count == 0)
|
if (allItems.Count == 0)
|
||||||
{
|
{
|
||||||
return podContents;
|
return podContents;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace WulaFallenEmpire
|
|||||||
private Vector2 scrollPosition;
|
private Vector2 scrollPosition;
|
||||||
private float viewHeight;
|
private float viewHeight;
|
||||||
|
|
||||||
private List<Tradeable_StorageTransfer> tradeables = new List<Tradeable_StorageTransfer>();
|
private List<Tradeable> tradeables = new List<Tradeable>();
|
||||||
|
|
||||||
private ITrader prevTrader;
|
private ITrader prevTrader;
|
||||||
private Pawn prevNegotiator;
|
private Pawn prevNegotiator;
|
||||||
@@ -117,7 +117,7 @@ namespace WulaFallenEmpire
|
|||||||
|
|
||||||
for (int i = 0; i < tradeables.Count; i++)
|
for (int i = 0; i < tradeables.Count; i++)
|
||||||
{
|
{
|
||||||
Tradeable_StorageTransfer trad = tradeables[i];
|
Tradeable trad = tradeables[i];
|
||||||
if (trad == null || trad.ThingDef == null) continue;
|
if (trad == null || trad.ThingDef == null) continue;
|
||||||
|
|
||||||
if (!quickSearchWidget.filter.Matches(trad.ThingDef))
|
if (!quickSearchWidget.filter.Matches(trad.ThingDef))
|
||||||
@@ -187,42 +187,48 @@ namespace WulaFallenEmpire
|
|||||||
{
|
{
|
||||||
tradeables.Clear();
|
tradeables.Clear();
|
||||||
|
|
||||||
var byDef = new Dictionary<ThingDef, Tradeable_StorageTransfer>();
|
void AddThingToTradeables(Thing thing, Transactor transactor)
|
||||||
|
{
|
||||||
|
if (thing == null) return;
|
||||||
|
|
||||||
|
Tradeable trad = TransferableUtility.TradeableMatching(thing, tradeables);
|
||||||
|
if (trad == null)
|
||||||
|
{
|
||||||
|
trad = thing is Pawn ? new Tradeable_StorageTransferPawn() : new Tradeable_StorageTransfer();
|
||||||
|
tradeables.Add(trad);
|
||||||
|
}
|
||||||
|
trad.AddThing(thing, transactor);
|
||||||
|
}
|
||||||
|
|
||||||
foreach (Thing t in GetThingsInPoweredTradeBeaconRange(table.Map))
|
foreach (Thing t in GetThingsInPoweredTradeBeaconRange(table.Map))
|
||||||
{
|
{
|
||||||
if (t?.def == null) continue;
|
if (t?.def == null) continue;
|
||||||
|
if (t is Corpse) continue;
|
||||||
if (t.def.category != ThingCategory.Item) continue;
|
if (t.def.category != ThingCategory.Item) continue;
|
||||||
|
AddThingToTradeables(t, Transactor.Colony);
|
||||||
if (!byDef.TryGetValue(t.def, out var trad))
|
|
||||||
{
|
|
||||||
trad = new Tradeable_StorageTransfer();
|
|
||||||
byDef[t.def] = trad;
|
|
||||||
}
|
|
||||||
trad.AddThing(t, Transactor.Colony);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var kvp in GetGlobalStorageCounts(storage))
|
if (storage?.inputContainer != null)
|
||||||
{
|
{
|
||||||
ThingDef def = kvp.Key;
|
foreach (Thing t in storage.inputContainer)
|
||||||
int count = kvp.Value;
|
|
||||||
if (def == null || count <= 0) continue;
|
|
||||||
|
|
||||||
if (!byDef.TryGetValue(def, out var trad))
|
|
||||||
{
|
{
|
||||||
trad = new Tradeable_StorageTransfer();
|
if (t == null) continue;
|
||||||
byDef[def] = trad;
|
AddThingToTradeables(t, Transactor.Trader);
|
||||||
}
|
|
||||||
|
|
||||||
foreach (Thing dummy in MakeDummyStacks(def, count))
|
|
||||||
{
|
|
||||||
trad.AddThing(dummy, Transactor.Trader);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tradeables = byDef.Values
|
if (storage?.outputContainer != null)
|
||||||
.Where(t => t != null && t.ThingDef != null)
|
{
|
||||||
.OrderBy(t => t.ThingDef.label)
|
foreach (Thing t in storage.outputContainer)
|
||||||
|
{
|
||||||
|
if (t == null) continue;
|
||||||
|
AddThingToTradeables(t, Transactor.Trader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tradeables = tradeables
|
||||||
|
.Where(t => t != null && t.HasAnyThing)
|
||||||
|
.OrderBy(t => t.ThingDef?.label ?? "")
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,68 +253,18 @@ namespace WulaFallenEmpire
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Dictionary<ThingDef, int> GetGlobalStorageCounts(GlobalStorageWorldComponent storage)
|
|
||||||
{
|
|
||||||
var counts = new Dictionary<ThingDef, int>();
|
|
||||||
if (storage == null) return counts;
|
|
||||||
|
|
||||||
foreach (var kvp in storage.outputStorage)
|
|
||||||
{
|
|
||||||
if (kvp.Key == null || kvp.Value <= 0) continue;
|
|
||||||
counts[kvp.Key] = counts.TryGetValue(kvp.Key, out var v) ? v + kvp.Value : kvp.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var kvp in storage.inputStorage)
|
|
||||||
{
|
|
||||||
if (kvp.Key == null || kvp.Value <= 0) continue;
|
|
||||||
counts[kvp.Key] = counts.TryGetValue(kvp.Key, out var v) ? v + kvp.Value : kvp.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return counts;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<Thing> MakeDummyStacks(ThingDef def, int count)
|
|
||||||
{
|
|
||||||
int remaining = count;
|
|
||||||
int stackLimit = Mathf.Max(1, def.stackLimit);
|
|
||||||
|
|
||||||
while (remaining > 0)
|
|
||||||
{
|
|
||||||
int stackCount = Mathf.Min(remaining, stackLimit);
|
|
||||||
Thing thing = MakeThingForDef(def, stackCount);
|
|
||||||
if (thing == null) yield break;
|
|
||||||
|
|
||||||
yield return thing;
|
|
||||||
remaining -= stackCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Thing MakeThingForDef(ThingDef def, int stackCount)
|
|
||||||
{
|
|
||||||
if (def == null) return null;
|
|
||||||
|
|
||||||
Thing thing;
|
|
||||||
if (def.MadeFromStuff)
|
|
||||||
{
|
|
||||||
ThingDef stuff = GenStuff.DefaultStuffFor(def) ?? GenStuff.AllowedStuffsFor(def).FirstOrDefault();
|
|
||||||
if (stuff == null) return null;
|
|
||||||
thing = ThingMaker.MakeThing(def, stuff);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
thing = ThingMaker.MakeThing(def);
|
|
||||||
}
|
|
||||||
|
|
||||||
thing.stackCount = stackCount;
|
|
||||||
return thing;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Tradeable_StorageTransfer : Tradeable
|
private class Tradeable_StorageTransfer : Tradeable
|
||||||
{
|
{
|
||||||
public override bool TraderWillTrade => true;
|
public override bool TraderWillTrade => true;
|
||||||
public override bool IsCurrency => false;
|
public override bool IsCurrency => false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class Tradeable_StorageTransferPawn : Tradeable_Pawn
|
||||||
|
{
|
||||||
|
public override bool TraderWillTrade => true;
|
||||||
|
public override bool IsCurrency => false;
|
||||||
|
}
|
||||||
|
|
||||||
private class GlobalStorageTransferTrader : ITrader
|
private class GlobalStorageTransferTrader : ITrader
|
||||||
{
|
{
|
||||||
private readonly Map map;
|
private readonly Map map;
|
||||||
@@ -347,14 +303,12 @@ namespace WulaFallenEmpire
|
|||||||
|
|
||||||
if (ShouldGoToOutputStorage(thing))
|
if (ShouldGoToOutputStorage(thing))
|
||||||
{
|
{
|
||||||
storage.AddToOutputStorage(thing.def, thing.stackCount);
|
storage.AddToOutputStorage(thing);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
storage.AddToInputStorage(thing.def, thing.stackCount);
|
storage.AddToInputStorage(thing);
|
||||||
}
|
}
|
||||||
|
|
||||||
thing.Destroy(DestroyMode.Vanish);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GiveSoldThingToPlayer(Thing toGive, int countToGive, Pawn playerNegotiator)
|
public void GiveSoldThingToPlayer(Thing toGive, int countToGive, Pawn playerNegotiator)
|
||||||
@@ -363,12 +317,6 @@ namespace WulaFallenEmpire
|
|||||||
if (map == null) return;
|
if (map == null) return;
|
||||||
if (toGive == null || countToGive <= 0) return;
|
if (toGive == null || countToGive <= 0) return;
|
||||||
|
|
||||||
if (!TryRemoveFromAnyStorage(toGive.def, countToGive))
|
|
||||||
{
|
|
||||||
Log.Warning($"[WULA] Global storage changed while transfer dialog open; could not remove {countToGive}x {toGive.def?.defName}.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Thing thing = toGive.SplitOff(countToGive);
|
Thing thing = toGive.SplitOff(countToGive);
|
||||||
thing.PreTraded(TradeAction.PlayerBuys, playerNegotiator, this);
|
thing.PreTraded(TradeAction.PlayerBuys, playerNegotiator, this);
|
||||||
|
|
||||||
@@ -384,33 +332,6 @@ namespace WulaFallenEmpire
|
|||||||
if (def.IsApparel) return true;
|
if (def.IsApparel) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryRemoveFromAnyStorage(ThingDef def, int count)
|
|
||||||
{
|
|
||||||
if (def == null || count <= 0) return false;
|
|
||||||
|
|
||||||
int available = storage.GetInputStorageCount(def) + storage.GetOutputStorageCount(def);
|
|
||||||
if (available < count) return false;
|
|
||||||
|
|
||||||
int remaining = count;
|
|
||||||
int fromOutput = Mathf.Min(remaining, storage.GetOutputStorageCount(def));
|
|
||||||
if (fromOutput > 0)
|
|
||||||
{
|
|
||||||
if (!storage.RemoveFromOutputStorage(def, fromOutput)) return false;
|
|
||||||
remaining -= fromOutput;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remaining > 0)
|
|
||||||
{
|
|
||||||
if (!storage.RemoveFromInputStorage(def, remaining))
|
|
||||||
{
|
|
||||||
if (fromOutput > 0) storage.AddToOutputStorage(def, fromOutput);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,15 +9,22 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace WulaFallenEmpire
|
namespace WulaFallenEmpire
|
||||||
{
|
{
|
||||||
public class GlobalStorageWorldComponent : WorldComponent
|
public class GlobalStorageWorldComponent : WorldComponent, IThingHolder
|
||||||
{
|
{
|
||||||
public Dictionary<ThingDef, int> inputStorage = new Dictionary<ThingDef, int>();
|
public Dictionary<ThingDef, int> inputStorage = new Dictionary<ThingDef, int>();
|
||||||
public Dictionary<ThingDef, int> outputStorage = new Dictionary<ThingDef, int>();
|
public Dictionary<ThingDef, int> outputStorage = new Dictionary<ThingDef, int>();
|
||||||
|
|
||||||
|
public ThingOwner<Thing> inputContainer;
|
||||||
|
public ThingOwner<Thing> outputContainer;
|
||||||
|
|
||||||
// 存储生产订单
|
// 存储生产订单
|
||||||
public List<GlobalProductionOrder> productionOrders = new List<GlobalProductionOrder>();
|
public List<GlobalProductionOrder> productionOrders = new List<GlobalProductionOrder>();
|
||||||
|
|
||||||
public GlobalStorageWorldComponent(World world) : base(world) { }
|
public GlobalStorageWorldComponent(World world) : base(world)
|
||||||
|
{
|
||||||
|
inputContainer = new ThingOwner<Thing>(this);
|
||||||
|
outputContainer = new ThingOwner<Thing>(this);
|
||||||
|
}
|
||||||
|
|
||||||
public override void ExposeData()
|
public override void ExposeData()
|
||||||
{
|
{
|
||||||
@@ -30,62 +37,194 @@ namespace WulaFallenEmpire
|
|||||||
// 序列化输出存储
|
// 序列化输出存储
|
||||||
Scribe_Collections.Look(ref outputStorage, "outputStorage", LookMode.Def, LookMode.Value);
|
Scribe_Collections.Look(ref outputStorage, "outputStorage", LookMode.Def, LookMode.Value);
|
||||||
if (outputStorage == null) outputStorage = new Dictionary<ThingDef, int>();
|
if (outputStorage == null) outputStorage = new Dictionary<ThingDef, int>();
|
||||||
|
|
||||||
|
Scribe_Deep.Look(ref inputContainer, "inputContainer", this);
|
||||||
|
Scribe_Deep.Look(ref outputContainer, "outputContainer", this);
|
||||||
|
if (inputContainer == null) inputContainer = new ThingOwner<Thing>(this);
|
||||||
|
if (outputContainer == null) outputContainer = new ThingOwner<Thing>(this);
|
||||||
|
|
||||||
// 序列化生产订单
|
// 序列化生产订单
|
||||||
Scribe_Collections.Look(ref productionOrders, "productionOrders", LookMode.Deep);
|
Scribe_Collections.Look(ref productionOrders, "productionOrders", LookMode.Deep);
|
||||||
if (productionOrders == null) productionOrders = new List<GlobalProductionOrder>();
|
if (productionOrders == null) productionOrders = new List<GlobalProductionOrder>();
|
||||||
|
|
||||||
|
if (Scribe.mode == LoadSaveMode.PostLoadInit)
|
||||||
|
{
|
||||||
|
MigrateLegacyDictionariesToThingOwnersIfNeeded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MigrateLegacyDictionariesToThingOwnersIfNeeded()
|
||||||
|
{
|
||||||
|
// 旧存档:只有按 ThingDef 计数的字典。尽量迁移成真实 Thing(旧存档本就不含品质/耐久等信息)。
|
||||||
|
if (inputContainer != null && inputContainer.Any) return;
|
||||||
|
if (outputContainer != null && outputContainer.Any) return;
|
||||||
|
|
||||||
|
if (inputStorage != null)
|
||||||
|
{
|
||||||
|
foreach (var kvp in inputStorage.ToList())
|
||||||
|
{
|
||||||
|
if (kvp.Key == null || kvp.Value <= 0) continue;
|
||||||
|
AddGeneratedToContainer(inputContainer, kvp.Key, kvp.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outputStorage != null)
|
||||||
|
{
|
||||||
|
foreach (var kvp in outputStorage.ToList())
|
||||||
|
{
|
||||||
|
if (kvp.Key == null || kvp.Value <= 0) continue;
|
||||||
|
AddGeneratedToContainer(outputContainer, kvp.Key, kvp.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inputStorage?.Clear();
|
||||||
|
outputStorage?.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddGeneratedToContainer(ThingOwner<Thing> container, ThingDef def, int count)
|
||||||
|
{
|
||||||
|
if (container == null || def == null || count <= 0) return;
|
||||||
|
|
||||||
|
int remaining = count;
|
||||||
|
while (remaining > 0)
|
||||||
|
{
|
||||||
|
if (def.race != null)
|
||||||
|
{
|
||||||
|
PawnKindDef pawnKind = DefDatabase<PawnKindDef>.AllDefs.FirstOrDefault(k => k.race == def);
|
||||||
|
if (pawnKind == null) break;
|
||||||
|
|
||||||
|
Pawn pawn = PawnGenerator.GeneratePawn(pawnKind, Faction.OfPlayer);
|
||||||
|
if (pawn == null) break;
|
||||||
|
|
||||||
|
container.TryAdd(pawn, false);
|
||||||
|
remaining -= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int stackCount = Mathf.Min(remaining, Mathf.Max(1, def.stackLimit));
|
||||||
|
ThingDef stuff = null;
|
||||||
|
if (def.MadeFromStuff)
|
||||||
|
{
|
||||||
|
stuff = GenStuff.DefaultStuffFor(def) ?? GenStuff.AllowedStuffsFor(def).FirstOrDefault();
|
||||||
|
if (stuff == null) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Thing thing = ThingMaker.MakeThing(def, stuff);
|
||||||
|
if (thing == null) break;
|
||||||
|
|
||||||
|
thing.stackCount = stackCount;
|
||||||
|
container.TryAdd(thing, true);
|
||||||
|
remaining -= stackCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ThingOwner GetDirectlyHeldThings()
|
||||||
|
{
|
||||||
|
return inputContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IThingHolder ParentHolder => null;
|
||||||
|
|
||||||
|
public void GetChildHolders(List<IThingHolder> outChildren)
|
||||||
|
{
|
||||||
|
ThingOwnerUtility.AppendThingHoldersFromThings(outChildren, inputContainer);
|
||||||
|
ThingOwnerUtility.AppendThingHoldersFromThings(outChildren, outputContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 输入存储方法
|
// 输入存储方法
|
||||||
public void AddToInputStorage(ThingDef thingDef, int count)
|
public void AddToInputStorage(ThingDef thingDef, int count)
|
||||||
{
|
{
|
||||||
if (inputStorage.ContainsKey(thingDef))
|
AddGeneratedToContainer(inputContainer, thingDef, count);
|
||||||
inputStorage[thingDef] += count;
|
}
|
||||||
else
|
|
||||||
inputStorage[thingDef] = count;
|
public bool AddToInputStorage(Thing thing, bool canMergeWithExistingStacks = true)
|
||||||
|
{
|
||||||
|
if (thing == null) return false;
|
||||||
|
if (thing.Spawned) thing.DeSpawn();
|
||||||
|
return inputContainer.TryAdd(thing, canMergeWithExistingStacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool RemoveFromInputStorage(ThingDef thingDef, int count)
|
public bool RemoveFromInputStorage(ThingDef thingDef, int count)
|
||||||
{
|
{
|
||||||
if (inputStorage.ContainsKey(thingDef) && inputStorage[thingDef] >= count)
|
return TryConsumeFromContainer(inputContainer, thingDef, count);
|
||||||
{
|
|
||||||
inputStorage[thingDef] -= count;
|
|
||||||
if (inputStorage[thingDef] <= 0)
|
|
||||||
inputStorage.Remove(thingDef);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetInputStorageCount(ThingDef thingDef)
|
public int GetInputStorageCount(ThingDef thingDef)
|
||||||
{
|
{
|
||||||
return inputStorage.ContainsKey(thingDef) ? inputStorage[thingDef] : 0;
|
return CountInContainer(inputContainer, thingDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 输出存储方法
|
// 输出存储方法
|
||||||
public void AddToOutputStorage(ThingDef thingDef, int count)
|
public void AddToOutputStorage(ThingDef thingDef, int count)
|
||||||
{
|
{
|
||||||
if (outputStorage.ContainsKey(thingDef))
|
AddGeneratedToContainer(outputContainer, thingDef, count);
|
||||||
outputStorage[thingDef] += count;
|
}
|
||||||
else
|
|
||||||
outputStorage[thingDef] = count;
|
public bool AddToOutputStorage(Thing thing, bool canMergeWithExistingStacks = true)
|
||||||
|
{
|
||||||
|
if (thing == null) return false;
|
||||||
|
if (thing.Spawned) thing.DeSpawn();
|
||||||
|
return outputContainer.TryAdd(thing, canMergeWithExistingStacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool RemoveFromOutputStorage(ThingDef thingDef, int count)
|
public bool RemoveFromOutputStorage(ThingDef thingDef, int count)
|
||||||
{
|
{
|
||||||
if (outputStorage.ContainsKey(thingDef) && outputStorage[thingDef] >= count)
|
return TryConsumeFromContainer(outputContainer, thingDef, count);
|
||||||
{
|
|
||||||
outputStorage[thingDef] -= count;
|
|
||||||
if (outputStorage[thingDef] <= 0)
|
|
||||||
outputStorage.Remove(thingDef);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetOutputStorageCount(ThingDef thingDef)
|
public int GetOutputStorageCount(ThingDef thingDef)
|
||||||
{
|
{
|
||||||
return outputStorage.ContainsKey(thingDef) ? outputStorage[thingDef] : 0;
|
return CountInContainer(outputContainer, thingDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetInputStorageTotalCount()
|
||||||
|
{
|
||||||
|
return inputContainer?.Sum(t => t?.stackCount ?? 0) ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetOutputStorageTotalCount()
|
||||||
|
{
|
||||||
|
return outputContainer?.Sum(t => t?.stackCount ?? 0) ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int CountInContainer(ThingOwner<Thing> container, ThingDef def)
|
||||||
|
{
|
||||||
|
if (container == null || def == null) return 0;
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < container.Count; i++)
|
||||||
|
{
|
||||||
|
Thing t = container[i];
|
||||||
|
if (t != null && t.def == def)
|
||||||
|
{
|
||||||
|
count += t.stackCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryConsumeFromContainer(ThingOwner<Thing> container, ThingDef def, int count)
|
||||||
|
{
|
||||||
|
if (container == null || def == null || count <= 0) return false;
|
||||||
|
|
||||||
|
if (CountInContainer(container, def) < count) return false;
|
||||||
|
|
||||||
|
int remaining = count;
|
||||||
|
for (int i = container.Count - 1; i >= 0 && remaining > 0; i--)
|
||||||
|
{
|
||||||
|
Thing t = container[i];
|
||||||
|
if (t == null || t.def != def) continue;
|
||||||
|
|
||||||
|
int take = Mathf.Min(t.stackCount, remaining);
|
||||||
|
Thing taken = t.SplitOff(take);
|
||||||
|
if (taken.holdingOwner != null)
|
||||||
|
{
|
||||||
|
taken.holdingOwner.Remove(taken);
|
||||||
|
}
|
||||||
|
taken.Destroy(DestroyMode.Vanish);
|
||||||
|
remaining -= take;
|
||||||
|
}
|
||||||
|
|
||||||
|
return remaining <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生产订单管理
|
// 生产订单管理
|
||||||
@@ -124,22 +263,13 @@ namespace WulaFallenEmpire
|
|||||||
|
|
||||||
if (workTable != null && workTable.Spawned)
|
if (workTable != null && workTable.Spawned)
|
||||||
{
|
{
|
||||||
foreach (var kvp in globalStorage.outputStorage.ToList()) // 使用ToList避免修改时枚举
|
for (int i = globalStorage.outputContainer.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
ThingDef thingDef = kvp.Key;
|
Thing thing = globalStorage.outputContainer[i];
|
||||||
int count = kvp.Value;
|
if (thing == null) continue;
|
||||||
|
|
||||||
while (count > 0)
|
globalStorage.outputContainer.Remove(thing);
|
||||||
{
|
GenPlace.TryPlaceThing(thing, workTable.Position, workTable.Map, ThingPlaceMode.Near);
|
||||||
int stackSize = Mathf.Min(count, thingDef.stackLimit);
|
|
||||||
Thing thing = ThingMaker.MakeThing(thingDef);
|
|
||||||
thing.stackCount = stackSize;
|
|
||||||
|
|
||||||
GenPlace.TryPlaceThing(thing, workTable.Position, workTable.Map, ThingPlaceMode.Near);
|
|
||||||
|
|
||||||
globalStorage.RemoveFromOutputStorage(thingDef, stackSize);
|
|
||||||
count -= stackSize;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Log.Message("Spawned all output products");
|
Log.Message("Spawned all output products");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -274,10 +274,12 @@ namespace WulaFallenEmpire
|
|||||||
// 输入存储(原材料)
|
// 输入存储(原材料)
|
||||||
sb.AppendLine("WULA_InputStorage".Translate() + ":");
|
sb.AppendLine("WULA_InputStorage".Translate() + ":");
|
||||||
sb.AppendLine();
|
sb.AppendLine();
|
||||||
var inputItems = globalStorage.inputStorage
|
var inputItems = globalStorage.inputContainer
|
||||||
.Where(kvp => kvp.Value > 0)
|
.Where(t => t != null && t.stackCount > 0)
|
||||||
.OrderByDescending(kvp => kvp.Value)
|
.GroupBy(t => t.def)
|
||||||
.ThenBy(kvp => kvp.Key.label)
|
.Select(g => new { Def = g.Key, Count = g.Sum(x => x.stackCount) })
|
||||||
|
.OrderByDescending(x => x.Count)
|
||||||
|
.ThenBy(x => x.Def.label)
|
||||||
.ToList();
|
.ToList();
|
||||||
if (inputItems.Count == 0)
|
if (inputItems.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -285,19 +287,21 @@ namespace WulaFallenEmpire
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach (var kvp in inputItems)
|
foreach (var x in inputItems)
|
||||||
{
|
{
|
||||||
sb.AppendLine($" {kvp.Value} {kvp.Key.LabelCap}");
|
sb.AppendLine($" {x.Count} {x.Def.LabelCap}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sb.AppendLine();
|
sb.AppendLine();
|
||||||
// 输出存储(产品)
|
// 输出存储(产品)
|
||||||
sb.AppendLine("WULA_OutputStorage".Translate() + ":");
|
sb.AppendLine("WULA_OutputStorage".Translate() + ":");
|
||||||
sb.AppendLine();
|
sb.AppendLine();
|
||||||
var outputItems = globalStorage.outputStorage
|
var outputItems = globalStorage.outputContainer
|
||||||
.Where(kvp => kvp.Value > 0)
|
.Where(t => t != null && t.stackCount > 0)
|
||||||
.OrderByDescending(kvp => kvp.Value)
|
.GroupBy(t => t.def)
|
||||||
.ThenBy(kvp => kvp.Key.label)
|
.Select(g => new { Def = g.Key, Count = g.Sum(x => x.stackCount) })
|
||||||
|
.OrderByDescending(x => x.Count)
|
||||||
|
.ThenBy(x => x.Def.label)
|
||||||
.ToList();
|
.ToList();
|
||||||
if (outputItems.Count == 0)
|
if (outputItems.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -305,9 +309,9 @@ namespace WulaFallenEmpire
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
foreach (var kvp in outputItems)
|
foreach (var x in outputItems)
|
||||||
{
|
{
|
||||||
sb.AppendLine($" {kvp.Value} {kvp.Key.LabelCap}");
|
sb.AppendLine($" {x.Count} {x.Def.LabelCap}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
@@ -356,34 +360,19 @@ namespace WulaFallenEmpire
|
|||||||
IntVec3 spawnCell = SelTable.Position;
|
IntVec3 spawnCell = SelTable.Position;
|
||||||
int totalSpawned = 0;
|
int totalSpawned = 0;
|
||||||
|
|
||||||
// 复制列表以避免修改时枚举
|
for (int i = globalStorage.outputContainer.Count - 1; i >= 0; i--)
|
||||||
var outputCopy = new Dictionary<ThingDef, int>(globalStorage.outputStorage);
|
|
||||||
|
|
||||||
foreach (var kvp in outputCopy)
|
|
||||||
{
|
{
|
||||||
ThingDef thingDef = kvp.Key;
|
Thing thing = globalStorage.outputContainer[i];
|
||||||
int count = kvp.Value;
|
if (thing == null) continue;
|
||||||
|
|
||||||
if (count > 0)
|
globalStorage.outputContainer.Remove(thing);
|
||||||
|
if (GenPlace.TryPlaceThing(thing, spawnCell, map, ThingPlaceMode.Near))
|
||||||
{
|
{
|
||||||
// 创建物品并放置到地图上
|
totalSpawned += thing.stackCount;
|
||||||
while (count > 0)
|
}
|
||||||
{
|
else
|
||||||
int stackSize = Mathf.Min(count, thingDef.stackLimit);
|
{
|
||||||
Thing thing = ThingMaker.MakeThing(thingDef);
|
globalStorage.outputContainer.TryAdd(thing, true);
|
||||||
thing.stackCount = stackSize;
|
|
||||||
|
|
||||||
if (GenPlace.TryPlaceThing(thing, spawnCell, map, ThingPlaceMode.Near))
|
|
||||||
{
|
|
||||||
globalStorage.RemoveFromOutputStorage(thingDef, stackSize);
|
|
||||||
count -= stackSize;
|
|
||||||
totalSpawned += stackSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,23 +94,23 @@ namespace WulaFallenEmpire
|
|||||||
StringBuilder outputItemsList = new StringBuilder();
|
StringBuilder outputItemsList = new StringBuilder();
|
||||||
|
|
||||||
// 1. 将物品分类转移到相应的存储
|
// 1. 将物品分类转移到相应的存储
|
||||||
foreach (Thing item in transporter.innerContainer)
|
foreach (Thing item in transporter.innerContainer.ToList())
|
||||||
{
|
{
|
||||||
if (ShouldGoToOutputStorage(item))
|
if (ShouldGoToOutputStorage(item))
|
||||||
{
|
{
|
||||||
// 发送到输出存储器
|
int moved = item.stackCount;
|
||||||
globalStorage.AddToOutputStorage(item.def, item.stackCount);
|
transporter.innerContainer.TryTransferToContainer(item, globalStorage.outputContainer, moved, true);
|
||||||
outputItemsCount += item.stackCount;
|
outputItemsCount += moved;
|
||||||
if (outputItemsList.Length > 0) outputItemsList.Append(", ");
|
if (outputItemsList.Length > 0) outputItemsList.Append(", ");
|
||||||
outputItemsList.Append($"{item.LabelCap} x{item.stackCount}");
|
outputItemsList.Append($"{item.LabelCap} x{moved}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 发送到输入存储器
|
int moved = item.stackCount;
|
||||||
globalStorage.AddToInputStorage(item.def, item.stackCount);
|
transporter.innerContainer.TryTransferToContainer(item, globalStorage.inputContainer, moved, true);
|
||||||
inputItemsCount += item.stackCount;
|
inputItemsCount += moved;
|
||||||
if (inputItemsList.Length > 0) inputItemsList.Append(", ");
|
if (inputItemsList.Length > 0) inputItemsList.Append(", ");
|
||||||
inputItemsList.Append($"{item.LabelCap} x{item.stackCount}");
|
inputItemsList.Append($"{item.LabelCap} x{moved}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
<DebugType>pdbonly</DebugType>
|
<DebugType>pdbonly</DebugType>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
<OutputPath>bin\Release\</OutputPath>
|
<OutputPath>..\..\1.6\1.6\Assemblies\</OutputPath>
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
@@ -82,4 +82,4 @@
|
|||||||
<RemoveDir Directories="$(ProjectDir)obj\Debug" />
|
<RemoveDir Directories="$(ProjectDir)obj\Debug" />
|
||||||
<RemoveDir Directories="$(ProjectDir)obj\Release" />
|
<RemoveDir Directories="$(ProjectDir)obj\Release" />
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
Reference in New Issue
Block a user