From 647622e6187bb082b06b054342a71c1cf8b95f9a Mon Sep 17 00:00:00 2001 From: Sn1p3rr3c0n Date: Sun, 4 Sep 2022 19:48:20 +0200 Subject: [PATCH] #612 Added WealthWatcher Patch (may be toggeld) Added support for Orbital Trading Fixed issue when creating ThingOwner Fixed Typos in Conditional Patches Fixed Null ref issue for DSU Moved code to better locations --- Languages/English/Keyed/AllKeyed_Settings.xml | 2 + .../Common/ConditionalPatchHelper.cs | 10 ++- .../HarmonyPatches/Patch_DSU_OrbitalTrade.cs | 29 +++++++- .../Patch_TradeDeal_InSellablePosition.cs | 41 ++++++++++++ ...atch_WealthWatcher_CalculateWealthItems.cs | 29 ++++++++ .../Common/PRFMapComponent.cs | 20 ++++++ .../Common/ProjectRimFactory_ModComponent.cs | 1 + .../Common/ProjectRimFactory_ModSettings.cs | 20 ++++-- .../Storage/Building_ColdStorage.cs | 67 +++++-------------- .../Storage/Building_ColdStoragePowerd.cs | 10 +++ .../Building_MassStorageUnitPowered.cs | 22 +----- .../Storage/ILinkableStorageParent.cs | 49 ++++++++++++++ 12 files changed, 219 insertions(+), 81 deletions(-) create mode 100644 Source/ProjectRimFactory/Common/HarmonyPatches/Patch_TradeDeal_InSellablePosition.cs create mode 100644 Source/ProjectRimFactory/Common/HarmonyPatches/Patch_WealthWatcher_CalculateWealthItems.cs create mode 100644 Source/ProjectRimFactory/Storage/ILinkableStorageParent.cs diff --git a/Languages/English/Keyed/AllKeyed_Settings.xml b/Languages/English/Keyed/AllKeyed_Settings.xml index b319444a..948a4794 100644 --- a/Languages/English/Keyed/AllKeyed_Settings.xml +++ b/Languages/English/Keyed/AllKeyed_Settings.xml @@ -7,6 +7,8 @@ Patches Toggels the Advanced IO CanReach Patch\nWhen checked the Patch is active and allowes Pawns to reach DSU contents using Advanced IO Ports even if the Path to the DSU is blocked\nPatch is not active by default as it may cause spikes and is only usefull in some cases.\n(ProjectRimFactory.Common.HarmonyPatches.Patch_Reachability_CanReach:Prefix) Advanced IO CanReach + Toggels the Cold Storage WealthWatcher Patch\nWhen checked the Patch is active and items in Coldstorage contribute to Colony Wealth.\nFor most Players we reccomend this to be on.\nPeformence load on this is ~1ms per 1k Things stored. This runs every 5k Ticks\n(ProjectRimFactory.Common.HarmonyPatches.Patch_WealthWatcher_CalculateWealthItems:Postfix) + Cold Storage WealthWatcher Forbid items on Placment Toggle this to forbid items on placement diff --git a/Source/ProjectRimFactory/Common/ConditionalPatchHelper.cs b/Source/ProjectRimFactory/Common/ConditionalPatchHelper.cs index 2cdd61a4..715b79f1 100644 --- a/Source/ProjectRimFactory/Common/ConditionalPatchHelper.cs +++ b/Source/ProjectRimFactory/Common/ConditionalPatchHelper.cs @@ -62,6 +62,12 @@ public void PatchHandler(bool patch) AccessTools.Method(typeof(ProjectRimFactory.Common.HarmonyPatches.Patch_Reachability_CanReach), "Prefix") ); + public static TogglePatch Patch_WealthWatcher_CalculateWealthItems = new TogglePatch( + AccessTools.Method(typeof(RimWorld.WealthWatcher), "CalculateWealthItems"), + null, + AccessTools.Method(typeof(ProjectRimFactory.Common.HarmonyPatches.Patch_WealthWatcher_CalculateWealthItems), "Postfix") + ); + //Storage Patches public static TogglePatch Patch_MinifiedThing_Print = new TogglePatch( AccessTools.Method(typeof(RimWorld.MinifiedThing), "Print", new Type[] { typeof(SectionLayer)}), @@ -72,7 +78,7 @@ public void PatchHandler(bool patch) AccessTools.Method(typeof(ProjectRimFactory.Common.HarmonyPatches.Patch_Thing_Print), "Prefix") ); public static TogglePatch Patch_ThingWithComps_Draw = new TogglePatch( - AccessTools.Method(typeof(Verse.ThingWithComps), "Print", new Type[] { typeof(SectionLayer) }), + AccessTools.Method(typeof(Verse.ThingWithComps), "Draw"), AccessTools.Method(typeof(ProjectRimFactory.Common.HarmonyPatches.Patch_ThingWithComps_Draw), "Prefix") ); public static TogglePatch Patch_ThingWithComps_DrawGUIOverlay = new TogglePatch( @@ -80,7 +86,7 @@ public void PatchHandler(bool patch) AccessTools.Method(typeof(ProjectRimFactory.Common.HarmonyPatches.Patch_ThingWithComps_DrawGUIOverlay), "Prefix") ); public static TogglePatch Patch_Thing_DrawGUIOverlay = new TogglePatch( - AccessTools.Method(typeof(Verse.ThingWithComps), "DrawGUIOverlay"), + AccessTools.Method(typeof(Verse.Thing), "DrawGUIOverlay"), AccessTools.Method(typeof(ProjectRimFactory.Common.HarmonyPatches.Patch_Thing_DrawGUIOverlay), "Prefix") ); public static TogglePatch Patch_FloatMenuMakerMap_ChoicesAtFor = new TogglePatch( diff --git a/Source/ProjectRimFactory/Common/HarmonyPatches/Patch_DSU_OrbitalTrade.cs b/Source/ProjectRimFactory/Common/HarmonyPatches/Patch_DSU_OrbitalTrade.cs index d12eb071..b92c429f 100644 --- a/Source/ProjectRimFactory/Common/HarmonyPatches/Patch_DSU_OrbitalTrade.cs +++ b/Source/ProjectRimFactory/Common/HarmonyPatches/Patch_DSU_OrbitalTrade.cs @@ -20,7 +20,7 @@ static void Postfix(Map map, ref IEnumerable __result) { HashSet yieldedThings = new HashSet(); yieldedThings.AddRange(__result); - foreach (Building_MassStorageUnitPowered dsu in Building_MassStorageUnitPowered.AllPowered(map)) + foreach (ILinkableStorageParent dsu in TradePatchHelper.AllPowered(map)) { yieldedThings.AddRange(dsu.StoredItems); } @@ -89,7 +89,7 @@ static IEnumerable Transpiler(IEnumerable inst yield return new CodeInstruction(OpCodes.Call, AccessTools.PropertyGetter(typeof(PassingShip), "Map")); //Call --> Building_MassStorageUnitPowered.AnyPowerd with the above as an argument yield return new CodeInstruction(OpCodes.Call, HarmonyLib.AccessTools - .Method(typeof(Building_MassStorageUnitPowered) ,nameof(Building_MassStorageUnitPowered.AnyPowerd), new[] { typeof(Map)} )); + .Method(typeof(TradePatchHelper) ,nameof(TradePatchHelper.AnyPowerd), new[] { typeof(Map)} )); yield return new CodeInstruction(OpCodes.Brtrue_S, instruction.operand); continue; @@ -103,6 +103,31 @@ static IEnumerable Transpiler(IEnumerable inst } } + public static class TradePatchHelper + { + public static bool AnyPowerd(Map map) + { + return AllPowered(map,true).Any(); + } + + public static IEnumerable AllPowered(Map map, bool any = false) + { + foreach (ILinkableStorageParent item in map.listerBuildings.AllBuildingsColonistOfClass()) + { + if (item.Powered) + { + yield return item; + if (any) break; + } + } + var cs = PatchStorageUtil.GetPRFMapComponent(map).ColdStorageBuildings.Select(b => b as ILinkableStorageParent); + foreach (var item in cs) + { + yield return item; + } + } + } + diff --git a/Source/ProjectRimFactory/Common/HarmonyPatches/Patch_TradeDeal_InSellablePosition.cs b/Source/ProjectRimFactory/Common/HarmonyPatches/Patch_TradeDeal_InSellablePosition.cs new file mode 100644 index 00000000..4647c60e --- /dev/null +++ b/Source/ProjectRimFactory/Common/HarmonyPatches/Patch_TradeDeal_InSellablePosition.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using RimWorld; +using HarmonyLib; +using Verse; +using ProjectRimFactory.Storage; +using System.Reflection.Emit; +using System.Reflection; + +namespace ProjectRimFactory.Common.HarmonyPatches +{ + + [HarmonyPatch(typeof(TradeDeal), "InSellablePosition")] + class Patch_TradeDeal_InSellablePosition + { + public static bool Prefix(Thing t, out string reason, ref bool __result) + { + if (!t.Spawned) + { + var buildings = PatchStorageUtil.GetPRFMapComponent(t.MapHeld).ColdStorageBuildings; + foreach(var building in buildings) + { + if (building.StoredItems.Contains(t)) + { + reason = null; + __result = true; + return false; + } + } + } + + reason = null; + return true; + } + + + } +} diff --git a/Source/ProjectRimFactory/Common/HarmonyPatches/Patch_WealthWatcher_CalculateWealthItems.cs b/Source/ProjectRimFactory/Common/HarmonyPatches/Patch_WealthWatcher_CalculateWealthItems.cs new file mode 100644 index 00000000..f653c70e --- /dev/null +++ b/Source/ProjectRimFactory/Common/HarmonyPatches/Patch_WealthWatcher_CalculateWealthItems.cs @@ -0,0 +1,29 @@ +using HarmonyLib; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProjectRimFactory.Common.HarmonyPatches +{ + /// + /// Patch to ensure Items in Cold Storage Contribute to Wealth + /// 1k Items ~ 1ms (every 5k Ticks) + /// + class Patch_WealthWatcher_CalculateWealthItems + { + + public static void Postfix(Verse.Map ___map, ref float __result) + { + var buildings = PatchStorageUtil.GetPRFMapComponent(___map).ColdStorageBuildings; + var cnt = buildings.Count; + for(int i = 0; i < cnt; i++) + { + var building = buildings[i]; + __result += building.GetItemWealth(); + } + + } + } +} diff --git a/Source/ProjectRimFactory/Common/PRFMapComponent.cs b/Source/ProjectRimFactory/Common/PRFMapComponent.cs index 02cbcecc..0e7f33ba 100644 --- a/Source/ProjectRimFactory/Common/PRFMapComponent.cs +++ b/Source/ProjectRimFactory/Common/PRFMapComponent.cs @@ -15,6 +15,8 @@ public class PRFMapComponent : MapComponent // iHideRightMenus: see HarmonyPatches/PatchStorage.cs public HashSet iHideRightMenus = new HashSet(); + public List ColdStorageBuildings = new List(); + private Dictionary> hideItemLocations = new Dictionary>(); private Dictionary> ForbidPawnOutputItemLocations = new Dictionary>(); @@ -23,6 +25,24 @@ public class PRFMapComponent : MapComponent public Dictionary GetadvancedIOLocations => advancedIOLocations; + public void RegisterColdStorageBuilding(ProjectRimFactory.Storage.Building_ColdStorage port) + { + if (!ColdStorageBuildings.Contains(port)) + { + ColdStorageBuildings.Add(port); + } + } + public void DeRegisterColdStorageBuilding(ProjectRimFactory.Storage.Building_ColdStorage port) + { + if (ColdStorageBuildings.Contains(port)) + { + ColdStorageBuildings.Remove(port); + } + + } + + + public void RegisteradvancedIOLocations(IntVec3 pos, ProjectRimFactory.Storage.Building_AdvancedStorageUnitIOPort port) { if (!advancedIOLocations.ContainsKey(pos)) diff --git a/Source/ProjectRimFactory/Common/ProjectRimFactory_ModComponent.cs b/Source/ProjectRimFactory/Common/ProjectRimFactory_ModComponent.cs index cb298220..cdcdc064 100644 --- a/Source/ProjectRimFactory/Common/ProjectRimFactory_ModComponent.cs +++ b/Source/ProjectRimFactory/Common/ProjectRimFactory_ModComponent.cs @@ -27,6 +27,7 @@ public ProjectRimFactory_ModComponent(ModContentPack content) : base(content) LoadModSupport(); ConditionalPatchHelper.InitHarmony(this.HarmonyInstance); ConditionalPatchHelper.Patch_Reachability_CanReach.PatchHandler(ProjectRimFactory_ModSettings.PRF_Patch_Reachability_CanReach); + ConditionalPatchHelper.Patch_Reachability_CanReach.PatchHandler(ProjectRimFactory_ModSettings.PRF_Patch_WealthWatcher_CalculateWealthItems); } catch (Exception ex) diff --git a/Source/ProjectRimFactory/Common/ProjectRimFactory_ModSettings.cs b/Source/ProjectRimFactory/Common/ProjectRimFactory_ModSettings.cs index 64952477..3b5e2458 100644 --- a/Source/ProjectRimFactory/Common/ProjectRimFactory_ModSettings.cs +++ b/Source/ProjectRimFactory/Common/ProjectRimFactory_ModSettings.cs @@ -73,12 +73,18 @@ private static void CSharpSettings(Listing_Standard list) { } TooltipHandler.TipRegion(rect, "PRF_Settings_C_Patches_Reachability_CanReach_ToolTip".Translate()); Widgets.CheckboxLabeled(rect, "PRF_Settings_C_Patches_Reachability_CanReach".Translate(), ref PRF_Patch_Reachability_CanReach); - list.Gap(); - if (PRF_Patch_Reachability_CanReach != PRF_Patch_Reachability_CanReach_last) + list.Gap(); + ConditionalPatchHelper.Patch_Reachability_CanReach.PatchHandler(ProjectRimFactory_ModSettings.PRF_Patch_Reachability_CanReach); + + rect = list.GetRect(20); + if (Mouse.IsOver(rect)) { - ConditionalPatchHelper.Patch_Reachability_CanReach.PatchHandler(ProjectRimFactory_ModSettings.PRF_Patch_Reachability_CanReach); - } - PRF_Patch_Reachability_CanReach_last = PRF_Patch_Reachability_CanReach; + Widgets.DrawHighlight(rect); + } + TooltipHandler.TipRegion(rect, "PRF_Settings_C_Patches_WealthWatcher_CalculateWealthItems_ToolTip".Translate()); + Widgets.CheckboxLabeled(rect, "PRF_Settings_C_Patches_WealthWatcher_CalculateWealthItems".Translate(), ref PRF_Patch_WealthWatcher_CalculateWealthItems); + list.Gap(); + ConditionalPatchHelper.Patch_Reachability_CanReach.PatchHandler(ProjectRimFactory_ModSettings.PRF_Patch_WealthWatcher_CalculateWealthItems); } @@ -104,7 +110,7 @@ private static ContainerRow ParseSettingRows(ModContentPack content) public static bool PRF_LiteMode = false; private static bool PRF_LiteMode_last = false; public static bool PRF_Patch_Reachability_CanReach = false; - private static bool PRF_Patch_Reachability_CanReach_last = false; + public static bool PRF_Patch_WealthWatcher_CalculateWealthItems = true; public override void ExposeData() { @@ -113,8 +119,8 @@ public override void ExposeData() Scribe_Values.Look(ref Debug.activeFlags, "debugFlags", 0); Scribe_Values.Look(ref PRF_LiteMode, "PRF_LiteMode", false); Scribe_Values.Look(ref PRF_Patch_Reachability_CanReach, "PRF_Patch_Reachability_CanReach", false); + Scribe_Values.Look(ref PRF_Patch_WealthWatcher_CalculateWealthItems, "PRF_Patch_WealthWatcher_CalculateWealthItems", true); PRF_LiteMode_last = PRF_LiteMode; - PRF_Patch_Reachability_CanReach_last = PRF_Patch_Reachability_CanReach; } public void DoWindowContents(Rect inRect) diff --git a/Source/ProjectRimFactory/Storage/Building_ColdStorage.cs b/Source/ProjectRimFactory/Storage/Building_ColdStorage.cs index 14cd44cf..ff7d540c 100644 --- a/Source/ProjectRimFactory/Storage/Building_ColdStorage.cs +++ b/Source/ProjectRimFactory/Storage/Building_ColdStorage.cs @@ -11,53 +11,12 @@ namespace ProjectRimFactory.Storage { - public interface ILinkableStorageParent - { - public List StoredItems { get; } - - public bool AdvancedIOAllowed { get; } - - public void HandleNewItem(Thing item); - - public void HandleMoveItem(Thing item); - - public bool CanReciveThing(Thing item); - - public bool HoldsPos(IntVec3 pos); - - //What is that even for ?? - public void DeregisterPort(Building_StorageUnitIOBase port); - public void RegisterPort(Building_StorageUnitIOBase port); - - public StorageSettings GetSettings { get; } - - public IntVec3 GetPosition { get; } - - public string LabelCap { get; } - public bool CanReceiveIO { get; } - public Map Map { get; } - - public int StoredItemsCount { get; } - - public string GetITabString(int itemsSelected); - - public LocalTargetInfo GetTargetInfo { get; } - - public bool OutputItem(Thing item); - - public bool Powered { get; } - - public bool CanUseIOPort { get; } - - } - - [StaticConstructorOnStartup] public abstract class Building_ColdStorage : Building, IRenameBuilding, IHaulDestination, IStoreSettingsParent, ILinkableStorageParent, IThingHolder { private static readonly Texture2D RenameTex = ContentFinder.Get("UI/Buttons/Rename"); - protected ThingOwner thingOwner = new ThingOwner(); + protected ThingOwner thingOwner; private List items => thingOwner.InnerListForReading; @@ -199,25 +158,22 @@ public override string GetInspectString() public override void DeSpawn(DestroyMode mode = DestroyMode.Vanish) { - var thingsToSplurge = new List(Position.GetThingList(Map)); + var thingsToSplurge = items; for (var i = 0; i < thingsToSplurge.Count; i++) if (thingsToSplurge[i].def.category == ThingCategory.Item) { - thingsToSplurge[i].DeSpawn(); + //thingsToSplurge[i].DeSpawn(); GenPlace.TryPlaceThing(thingsToSplurge[i], Position, Map, ThingPlaceMode.Near); } + PatchStorageUtil.GetPRFMapComponent(Map).DeRegisterColdStorageBuilding(this); base.DeSpawn(mode); } public override void SpawnSetup(Map map, bool respawningAfterLoad) { base.SpawnSetup(map, respawningAfterLoad); + PatchStorageUtil.GetPRFMapComponent(Map).RegisterColdStorageBuilding(this); ModExtension_Crate ??= def.GetModExtension(); - /*Log.Message("----------------"); - foreach (var item in this.StoredItems) - { - Log.Message(item.ToString()); - }*/ foreach (var port in ports) { if (port?.Spawned ?? false) @@ -231,6 +187,19 @@ public override void SpawnSetup(Map map, bool respawningAfterLoad) } + public float GetItemWealth() + { + float output = 0; + var itemsc = items.Count; + for (int i = 0;i< itemsc; i++) + { + var item = items[i]; + output += item.MarketValue * item.stackCount; + } + + return output; + } + public override void DrawGUIOverlay() { base.DrawGUIOverlay(); diff --git a/Source/ProjectRimFactory/Storage/Building_ColdStoragePowerd.cs b/Source/ProjectRimFactory/Storage/Building_ColdStoragePowerd.cs index 73478702..70d0ca81 100644 --- a/Source/ProjectRimFactory/Storage/Building_ColdStoragePowerd.cs +++ b/Source/ProjectRimFactory/Storage/Building_ColdStoragePowerd.cs @@ -152,5 +152,15 @@ public static IEnumerable AllPowered(Map map) } } + public override void SpawnSetup(Map map, bool respawningAfterLoad) + { + base.SpawnSetup(map, respawningAfterLoad); + } + + public override void PostMake() + { + base.PostMake(); + thingOwner ??= new ThingOwner(this); + } } } diff --git a/Source/ProjectRimFactory/Storage/Building_MassStorageUnitPowered.cs b/Source/ProjectRimFactory/Storage/Building_MassStorageUnitPowered.cs index aa36b610..29a46753 100644 --- a/Source/ProjectRimFactory/Storage/Building_MassStorageUnitPowered.cs +++ b/Source/ProjectRimFactory/Storage/Building_MassStorageUnitPowered.cs @@ -21,7 +21,7 @@ public class Building_MassStorageUnitPowered : Building_MassStorageUnit public override bool CanStoreMoreItems => (Powered) && this.Spawned && (ModExtension_Crate == null || StoredItemsCount < MaxNumberItemsInternal); - public override bool CanReceiveIO => base.CanReceiveIO && compPowerTrader.PowerOn && this.Spawned; + public override bool CanReceiveIO => base.CanReceiveIO && Powered && this.Spawned; public override bool ForbidPawnInput => this.ForbidPawnAccess || !this.pawnAccess || !this.CanStoreMoreItems; @@ -150,25 +150,5 @@ public override string GetITabString(int itemsSelected) return base.GetITabString(itemsSelected); } } - - //This Exists as I don't know how to call .Any() with CodeInstruction - //Can be removed if the Transpiler is Updated to inclued that - public static bool AnyPowerd(Map map) - { - return AllPowered(map).Any(); - } - - public static IEnumerable AllPowered(Map map) - { - foreach (Building_MassStorageUnitPowered item in map.listerBuildings.AllBuildingsColonistOfClass()) - { - CompPowerTrader comp = item.GetComp(); - if (comp == null || comp.PowerOn) - { - yield return item; - } - } - } - } } diff --git a/Source/ProjectRimFactory/Storage/ILinkableStorageParent.cs b/Source/ProjectRimFactory/Storage/ILinkableStorageParent.cs new file mode 100644 index 00000000..2ce05f9c --- /dev/null +++ b/Source/ProjectRimFactory/Storage/ILinkableStorageParent.cs @@ -0,0 +1,49 @@ +using System.Collections.Generic; +using RimWorld; +using Verse; + +namespace ProjectRimFactory.Storage +{ + /// + /// Interface for buildings that can have IO Ports link to them + /// + public interface ILinkableStorageParent + { + public List StoredItems { get; } + + public bool AdvancedIOAllowed { get; } + + public void HandleNewItem(Thing item); + + public void HandleMoveItem(Thing item); + + public bool CanReciveThing(Thing item); + + public bool HoldsPos(IntVec3 pos); + + //What is that even for ?? + public void DeregisterPort(Building_StorageUnitIOBase port); + public void RegisterPort(Building_StorageUnitIOBase port); + + public StorageSettings GetSettings { get; } + + public IntVec3 GetPosition { get; } + + public string LabelCap { get; } + public bool CanReceiveIO { get; } + public Map Map { get; } + + public int StoredItemsCount { get; } + + public string GetITabString(int itemsSelected); + + public LocalTargetInfo GetTargetInfo { get; } + + public bool OutputItem(Thing item); + + public bool Powered { get; } + + public bool CanUseIOPort { get; } + + } +} \ No newline at end of file