refactor(GlobalStorage): rewrite transfer dialog logic to remove TradeSession dependency and implement custom UI rendering
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -15,9 +15,7 @@ namespace WulaFallenEmpire
|
|||||||
private const float TopAreaHeight = 58f;
|
private const float TopAreaHeight = 58f;
|
||||||
|
|
||||||
private readonly Building_GlobalWorkTable table;
|
private readonly Building_GlobalWorkTable table;
|
||||||
private readonly Pawn negotiator;
|
|
||||||
private readonly GlobalStorageWorldComponent storage;
|
private readonly GlobalStorageWorldComponent storage;
|
||||||
private readonly GlobalStorageTransferTrader trader;
|
|
||||||
|
|
||||||
private readonly QuickSearchWidget quickSearchWidget = new QuickSearchWidget();
|
private readonly QuickSearchWidget quickSearchWidget = new QuickSearchWidget();
|
||||||
private Vector2 scrollPosition;
|
private Vector2 scrollPosition;
|
||||||
@@ -25,19 +23,12 @@ namespace WulaFallenEmpire
|
|||||||
|
|
||||||
private List<Tradeable> tradeables = new List<Tradeable>();
|
private List<Tradeable> tradeables = new List<Tradeable>();
|
||||||
|
|
||||||
private ITrader prevTrader;
|
|
||||||
private Pawn prevNegotiator;
|
|
||||||
private TradeDeal prevDeal;
|
|
||||||
private bool prevGiftMode;
|
|
||||||
|
|
||||||
public override Vector2 InitialSize => new Vector2(1024f, UI.screenHeight);
|
public override Vector2 InitialSize => new Vector2(1024f, UI.screenHeight);
|
||||||
|
|
||||||
public Dialog_GlobalStorageTransfer(Building_GlobalWorkTable table, Pawn negotiator)
|
public Dialog_GlobalStorageTransfer(Building_GlobalWorkTable table, Pawn negotiator)
|
||||||
{
|
{
|
||||||
this.table = table;
|
this.table = table;
|
||||||
this.negotiator = negotiator;
|
|
||||||
storage = Find.World.GetComponent<GlobalStorageWorldComponent>();
|
storage = Find.World.GetComponent<GlobalStorageWorldComponent>();
|
||||||
trader = new GlobalStorageTransferTrader(table?.Map, storage);
|
|
||||||
|
|
||||||
doCloseX = true;
|
doCloseX = true;
|
||||||
closeOnAccept = false;
|
closeOnAccept = false;
|
||||||
@@ -48,30 +39,9 @@ namespace WulaFallenEmpire
|
|||||||
public override void PostOpen()
|
public override void PostOpen()
|
||||||
{
|
{
|
||||||
base.PostOpen();
|
base.PostOpen();
|
||||||
|
|
||||||
prevTrader = TradeSession.trader;
|
|
||||||
prevNegotiator = TradeSession.playerNegotiator;
|
|
||||||
prevDeal = TradeSession.deal;
|
|
||||||
prevGiftMode = TradeSession.giftMode;
|
|
||||||
|
|
||||||
TradeSession.trader = trader;
|
|
||||||
TradeSession.playerNegotiator = negotiator;
|
|
||||||
TradeSession.deal = null;
|
|
||||||
TradeSession.giftMode = false;
|
|
||||||
|
|
||||||
RebuildTradeables();
|
RebuildTradeables();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void PostClose()
|
|
||||||
{
|
|
||||||
base.PostClose();
|
|
||||||
|
|
||||||
TradeSession.trader = prevTrader;
|
|
||||||
TradeSession.playerNegotiator = prevNegotiator;
|
|
||||||
TradeSession.deal = prevDeal;
|
|
||||||
TradeSession.giftMode = prevGiftMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void DoWindowContents(Rect inRect)
|
public override void DoWindowContents(Rect inRect)
|
||||||
{
|
{
|
||||||
if (table == null || table.DestroyedOrNull() || table.Map == null || storage == null)
|
if (table == null || table.DestroyedOrNull() || table.Map == null || storage == null)
|
||||||
@@ -111,30 +81,119 @@ namespace WulaFallenEmpire
|
|||||||
Rect outRect = rect.ContractedBy(5f);
|
Rect outRect = rect.ContractedBy(5f);
|
||||||
Rect viewRect = new Rect(0f, 0f, outRect.width - 16f, viewHeight);
|
Rect viewRect = new Rect(0f, 0f, outRect.width - 16f, viewHeight);
|
||||||
|
|
||||||
Widgets.BeginScrollView(outRect, ref scrollPosition, viewRect);
|
|
||||||
float curY = 0f;
|
float curY = 0f;
|
||||||
int drawnIndex = 0;
|
int drawnIndex = 0;
|
||||||
|
|
||||||
for (int i = 0; i < tradeables.Count; i++)
|
Widgets.BeginScrollView(outRect, ref scrollPosition, viewRect);
|
||||||
|
try
|
||||||
{
|
{
|
||||||
Tradeable trad = tradeables[i];
|
for (int i = 0; i < tradeables.Count; i++)
|
||||||
if (trad == null || trad.ThingDef == null) continue;
|
{
|
||||||
|
Tradeable trad = tradeables[i];
|
||||||
|
if (trad == null || trad.ThingDef == null) continue;
|
||||||
|
|
||||||
if (!quickSearchWidget.filter.Matches(trad.ThingDef))
|
PruneTradeableThingLists(trad);
|
||||||
continue;
|
if (!trad.HasAnyThing) continue;
|
||||||
|
|
||||||
Rect rowRect = new Rect(0f, curY, viewRect.width, RowHeight);
|
if (!quickSearchWidget.filter.Matches(trad.ThingDef))
|
||||||
TradeUI.DrawTradeableRow(rowRect, trad, drawnIndex);
|
continue;
|
||||||
curY += RowHeight;
|
|
||||||
drawnIndex++;
|
Rect rowRect = new Rect(0f, curY, viewRect.width, RowHeight);
|
||||||
|
DrawStorageTransferRow(rowRect, trad, drawnIndex);
|
||||||
|
curY += RowHeight;
|
||||||
|
drawnIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Event.current.type == EventType.Layout)
|
||||||
|
{
|
||||||
|
viewHeight = Mathf.Max(curY, outRect.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
GenUI.ResetLabelAlign();
|
||||||
|
Widgets.EndScrollView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawStorageTransferRow(Rect rect, Tradeable trad, int index)
|
||||||
|
{
|
||||||
|
if (index % 2 == 1)
|
||||||
|
{
|
||||||
|
Widgets.DrawLightHighlight(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Event.current.type == EventType.Layout)
|
Text.Font = GameFont.Small;
|
||||||
|
Widgets.BeginGroup(rect);
|
||||||
|
try
|
||||||
{
|
{
|
||||||
viewHeight = Mathf.Max(curY, outRect.height);
|
float width = rect.width;
|
||||||
|
|
||||||
|
int globalCount = SafeCountHeldBy(trad, Transactor.Trader);
|
||||||
|
if (globalCount != 0 && trad.IsThing)
|
||||||
|
{
|
||||||
|
Rect countRect = new Rect(width - TradeUI.CountColumnWidth, 0f, TradeUI.CountColumnWidth, rect.height);
|
||||||
|
Widgets.DrawHighlightIfMouseover(countRect);
|
||||||
|
Text.Anchor = TextAnchor.MiddleRight;
|
||||||
|
Rect labelRect = countRect.ContractedBy(5f, 0f);
|
||||||
|
Widgets.Label(labelRect, globalCount.ToStringCached());
|
||||||
|
TooltipHandler.TipRegionByKey(countRect, "TraderCount");
|
||||||
|
}
|
||||||
|
|
||||||
|
width -= TradeUI.CountColumnWidth + TradeUI.PriceColumnWidth;
|
||||||
|
|
||||||
|
Rect adjustRect = new Rect(width - TradeUI.AdjustColumnWidth, 0f, TradeUI.AdjustColumnWidth, rect.height);
|
||||||
|
int min = -SafeCountHeldBy(trad, Transactor.Colony);
|
||||||
|
int max = SafeCountHeldBy(trad, Transactor.Trader);
|
||||||
|
TransferableUIUtility.DoCountAdjustInterface(adjustRect, trad, index, min, max, flash: false);
|
||||||
|
width -= TradeUI.AdjustColumnWidth;
|
||||||
|
|
||||||
|
int beaconCount = SafeCountHeldBy(trad, Transactor.Colony);
|
||||||
|
if (beaconCount != 0)
|
||||||
|
{
|
||||||
|
Rect countRect = new Rect(width - TradeUI.CountColumnWidth, 0f, TradeUI.CountColumnWidth, rect.height);
|
||||||
|
Widgets.DrawHighlightIfMouseover(countRect);
|
||||||
|
Text.Anchor = TextAnchor.MiddleLeft;
|
||||||
|
Rect labelRect = countRect.ContractedBy(5f, 0f);
|
||||||
|
Widgets.Label(labelRect, beaconCount.ToStringCached());
|
||||||
|
TooltipHandler.TipRegionByKey(countRect, "ColonyCount");
|
||||||
|
}
|
||||||
|
|
||||||
|
width -= TradeUI.CountColumnWidth + TradeUI.PriceColumnWidth;
|
||||||
|
|
||||||
|
Rect infoRect = new Rect(0f, 0f, width, rect.height);
|
||||||
|
TransferableUIUtility.DrawTransferableInfo(trad, infoRect, Color.white);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
GenUI.ResetLabelAlign();
|
||||||
|
Widgets.EndGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int SafeCountHeldBy(Tradeable trad, Transactor transactor)
|
||||||
|
{
|
||||||
|
if (trad == null) return 0;
|
||||||
|
|
||||||
|
List<Thing> list = (transactor == Transactor.Colony) ? trad.thingsColony : trad.thingsTrader;
|
||||||
|
if (list == null || list.Count == 0) return 0;
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < list.Count; i++)
|
||||||
|
{
|
||||||
|
Thing t = list[i];
|
||||||
|
if (t == null || t.Destroyed) continue;
|
||||||
|
count += t.stackCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widgets.EndScrollView();
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void PruneTradeableThingLists(Tradeable trad)
|
||||||
|
{
|
||||||
|
if (trad == null) return;
|
||||||
|
trad.thingsColony?.RemoveAll(t => t == null || t.Destroyed);
|
||||||
|
trad.thingsTrader?.RemoveAll(t => t == null || t.Destroyed);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawBottomButtons(Rect rect)
|
private void DrawBottomButtons(Rect rect)
|
||||||
@@ -160,27 +219,109 @@ namespace WulaFallenEmpire
|
|||||||
|
|
||||||
private void ExecuteTransfers()
|
private void ExecuteTransfers()
|
||||||
{
|
{
|
||||||
bool changed = false;
|
if (storage == null || table?.Map == null)
|
||||||
|
return;
|
||||||
|
|
||||||
foreach (var trad in tradeables)
|
bool changed = false;
|
||||||
|
Map map = table.Map;
|
||||||
|
IntVec3 dropSpot = DropCellFinder.TradeDropSpot(map);
|
||||||
|
|
||||||
|
for (int i = 0; i < tradeables.Count; i++)
|
||||||
{
|
{
|
||||||
|
Tradeable trad = tradeables[i];
|
||||||
if (trad == null) continue;
|
if (trad == null) continue;
|
||||||
if (trad.CountToTransfer == 0) continue;
|
if (trad.CountToTransfer == 0) continue;
|
||||||
|
|
||||||
changed = true;
|
PruneTradeableThingLists(trad);
|
||||||
trad.ResolveTrade();
|
if (!trad.HasAnyThing) continue;
|
||||||
|
|
||||||
|
int storeCount = trad.CountToTransferToDestination; // 信标 -> 全局(CountToTransfer<0)
|
||||||
|
int takeCount = trad.CountToTransferToSource; // 全局 -> 信标(CountToTransfer>0)
|
||||||
|
|
||||||
|
if (storeCount > 0)
|
||||||
|
{
|
||||||
|
changed |= TransferToGlobalStorage(trad, storeCount);
|
||||||
|
}
|
||||||
|
else if (takeCount > 0)
|
||||||
|
{
|
||||||
|
changed |= TransferFromGlobalStorage(trad, takeCount, map, dropSpot);
|
||||||
|
}
|
||||||
|
|
||||||
trad.ForceTo(0);
|
trad.ForceTo(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed)
|
if (!changed)
|
||||||
{
|
|
||||||
SoundDefOf.ExecuteTrade.PlayOneShotOnCamera();
|
|
||||||
RebuildTradeables();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
SoundDefOf.Tick_Low.PlayOneShotOnCamera();
|
SoundDefOf.Tick_Low.PlayOneShotOnCamera();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SoundDefOf.ExecuteTrade.PlayOneShotOnCamera();
|
||||||
|
RebuildTradeables();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TransferToGlobalStorage(Tradeable trad, int count)
|
||||||
|
{
|
||||||
|
if (trad == null || count <= 0 || storage == null) return false;
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
TransferableUtility.TransferNoSplit(trad.thingsColony, count, (Thing thing, int countToTransfer) =>
|
||||||
|
{
|
||||||
|
if (thing == null || thing.Destroyed || countToTransfer <= 0) return;
|
||||||
|
|
||||||
|
Thing split = thing.SplitOff(countToTransfer);
|
||||||
|
if (split == null) return;
|
||||||
|
|
||||||
|
if (ShouldGoToOutputStorage(split))
|
||||||
|
{
|
||||||
|
storage.AddToOutputStorage(split);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
storage.AddToInputStorage(split);
|
||||||
|
}
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TransferFromGlobalStorage(Tradeable trad, int count, Map map, IntVec3 dropSpot)
|
||||||
|
{
|
||||||
|
if (trad == null || count <= 0 || storage == null || map == null) return false;
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
TransferableUtility.TransferNoSplit(trad.thingsTrader, count, (Thing thing, int countToTransfer) =>
|
||||||
|
{
|
||||||
|
if (thing == null || thing.Destroyed || countToTransfer <= 0) return;
|
||||||
|
|
||||||
|
Thing split = thing.SplitOff(countToTransfer);
|
||||||
|
if (split == null) return;
|
||||||
|
|
||||||
|
if (split.holdingOwner != null)
|
||||||
|
{
|
||||||
|
split.holdingOwner.Remove(split);
|
||||||
|
}
|
||||||
|
if (split.Spawned)
|
||||||
|
{
|
||||||
|
split.DeSpawn();
|
||||||
|
}
|
||||||
|
|
||||||
|
TradeUtility.SpawnDropPod(dropSpot, map, split);
|
||||||
|
changed = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool ShouldGoToOutputStorage(Thing thing)
|
||||||
|
{
|
||||||
|
ThingDef def = thing?.def;
|
||||||
|
if (def == null) return false;
|
||||||
|
if (def.IsWeapon) return true;
|
||||||
|
if (def.IsApparel) return true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RebuildTradeables()
|
private void RebuildTradeables()
|
||||||
@@ -257,81 +398,16 @@ namespace WulaFallenEmpire
|
|||||||
{
|
{
|
||||||
public override bool TraderWillTrade => true;
|
public override bool TraderWillTrade => true;
|
||||||
public override bool IsCurrency => false;
|
public override bool IsCurrency => false;
|
||||||
|
public override bool Interactive => true;
|
||||||
|
public override TransferablePositiveCountDirection PositiveCountDirection => TransferablePositiveCountDirection.Source;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Tradeable_StorageTransferPawn : Tradeable_Pawn
|
private class Tradeable_StorageTransferPawn : Tradeable_Pawn
|
||||||
{
|
{
|
||||||
public override bool TraderWillTrade => true;
|
public override bool TraderWillTrade => true;
|
||||||
public override bool IsCurrency => false;
|
public override bool IsCurrency => false;
|
||||||
}
|
public override bool Interactive => true;
|
||||||
|
public override TransferablePositiveCountDirection PositiveCountDirection => TransferablePositiveCountDirection.Source;
|
||||||
private class GlobalStorageTransferTrader : ITrader
|
|
||||||
{
|
|
||||||
private readonly Map map;
|
|
||||||
private readonly GlobalStorageWorldComponent storage;
|
|
||||||
private readonly TraderKindDef traderKind;
|
|
||||||
|
|
||||||
public GlobalStorageTransferTrader(Map map, GlobalStorageWorldComponent storage)
|
|
||||||
{
|
|
||||||
this.map = map;
|
|
||||||
this.storage = storage;
|
|
||||||
|
|
||||||
traderKind =
|
|
||||||
DefDatabase<TraderKindDef>.GetNamedSilentFail("Orbital_ExoticGoods") ??
|
|
||||||
DefDatabase<TraderKindDef>.GetNamedSilentFail("Orbital_BulkGoods") ??
|
|
||||||
DefDatabase<TraderKindDef>.AllDefs.FirstOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TraderKindDef TraderKind => traderKind;
|
|
||||||
public IEnumerable<Thing> Goods => Enumerable.Empty<Thing>();
|
|
||||||
public int RandomPriceFactorSeed => 0;
|
|
||||||
public string TraderName => "WULA_GlobalStorageTransferTitle".Translate();
|
|
||||||
public bool CanTradeNow => true;
|
|
||||||
public float TradePriceImprovementOffsetForPlayer => 0f;
|
|
||||||
public Faction Faction => Faction.OfPlayer;
|
|
||||||
public TradeCurrency TradeCurrency => TradeCurrency.Silver;
|
|
||||||
|
|
||||||
public IEnumerable<Thing> ColonyThingsWillingToBuy(Pawn playerNegotiator) => Enumerable.Empty<Thing>();
|
|
||||||
|
|
||||||
public void GiveSoldThingToTrader(Thing toGive, int countToGive, Pawn playerNegotiator)
|
|
||||||
{
|
|
||||||
if (storage == null) return;
|
|
||||||
if (toGive == null || countToGive <= 0) return;
|
|
||||||
|
|
||||||
Thing thing = toGive.SplitOff(countToGive);
|
|
||||||
thing.PreTraded(TradeAction.PlayerSells, playerNegotiator, this);
|
|
||||||
|
|
||||||
if (ShouldGoToOutputStorage(thing))
|
|
||||||
{
|
|
||||||
storage.AddToOutputStorage(thing);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
storage.AddToInputStorage(thing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GiveSoldThingToPlayer(Thing toGive, int countToGive, Pawn playerNegotiator)
|
|
||||||
{
|
|
||||||
if (storage == null) return;
|
|
||||||
if (map == null) return;
|
|
||||||
if (toGive == null || countToGive <= 0) return;
|
|
||||||
|
|
||||||
Thing thing = toGive.SplitOff(countToGive);
|
|
||||||
thing.PreTraded(TradeAction.PlayerBuys, playerNegotiator, this);
|
|
||||||
|
|
||||||
IntVec3 dropSpot = DropCellFinder.TradeDropSpot(map);
|
|
||||||
TradeUtility.SpawnDropPod(dropSpot, map, thing);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool ShouldGoToOutputStorage(Thing thing)
|
|
||||||
{
|
|
||||||
ThingDef def = thing?.def;
|
|
||||||
if (def == null) return false;
|
|
||||||
if (def.IsWeapon) return true;
|
|
||||||
if (def.IsApparel) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user