Decompiled source of EvenMoreSpace v0.3.51
plugins/EvenMoreSpace.dll
Decompiled 5 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using I2.Loc; using Lamb.UI; using Lamb.UI.BuildMenu; using Pathfinding.ClipperLib; using Spine.Unity; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.U2D; using src.Extensions; [assembly: ComVisible(false)] [assembly: Guid("7e433b45-7d31-4eb4-9ec8-3f6f7cc9cfda")] [assembly: AssemblyFileVersion("0.3.51.0")] [assembly: AssemblyCopyright("")] [assembly: AssemblyProduct("EvenMoreSpace")] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyCompany("")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyTrademark("")] [assembly: AssemblyTitle("EvenMoreSpace")] [assembly: AssemblyDescription("Extra Woolhaven base expansion for Cult of the Lamb.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyVersion("0.3.51.0")] namespace EvenMoreSpace; [BepInPlugin("com.cotl.evenmorespace", "EvenMoreSpace", "0.3.51")] public sealed class EvenMoreSpacePlugin : BaseUnityPlugin { public const string PluginGuid = "com.cotl.evenmorespace"; public const string PluginName = "EvenMoreSpace"; public const string PluginVersion = "0.3.51"; internal static EvenMoreSpacePlugin Instance; internal static ManualLogSource Log; internal static Harmony HarmonyInstance; private bool _expansionRuntimePatchesInstalled; private float _nextRuntimePatchCheck; private void Awake() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown //IL_00ec: Expected O, but got Unknown //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Expected O, but got Unknown //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Expected O, but got Unknown //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Expected O, but got Unknown //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Expected O, but got Unknown //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Expected O, but got Unknown //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Expected O, but got Unknown //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Expected O, but got Unknown //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Expected O, but got Unknown //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Expected O, but got Unknown //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Expected O, but got Unknown //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_03cd: Expected O, but got Unknown //IL_03da: Unknown result type (might be due to invalid IL or missing references) //IL_03e4: Expected O, but got Unknown //IL_03e4: Unknown result type (might be due to invalid IL or missing references) //IL_03ee: Expected O, but got Unknown //IL_03fa: Unknown result type (might be due to invalid IL or missing references) //IL_0404: Expected O, but got Unknown //IL_0404: Unknown result type (might be due to invalid IL or missing references) //IL_040e: Expected O, but got Unknown //IL_041a: Unknown result type (might be due to invalid IL or missing references) //IL_0424: Expected O, but got Unknown //IL_0424: Unknown result type (might be due to invalid IL or missing references) //IL_042e: Expected O, but got Unknown //IL_043a: Unknown result type (might be due to invalid IL or missing references) //IL_0444: Expected O, but got Unknown //IL_0444: Unknown result type (might be due to invalid IL or missing references) //IL_044e: Expected O, but got Unknown //IL_045a: Unknown result type (might be due to invalid IL or missing references) //IL_0464: Expected O, but got Unknown //IL_0464: Unknown result type (might be due to invalid IL or missing references) //IL_046e: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; EvenMoreSpaceConfig.Bind(((BaseUnityPlugin)this).Config); HarmonyInstance = new Harmony("com.cotl.evenmorespace"); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(Interaction_PurchaseLand), "Start", (Type[])null, (Type[])null), new HarmonyMethod(typeof(PurchaseLandStartPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(Interaction_PurchaseLand), "OnInteract", (Type[])null, (Type[])null), new HarmonyMethod(typeof(PurchaseLandInteractPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(DLCLandController), "ShowSlot", (Type[])null, (Type[])null), new HarmonyMethod(typeof(DLCLandShowSlotPatch), "Prefix", (Type[])null), new HarmonyMethod(typeof(DLCLandShowSlotPatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(BiomeBaseManager), "ActivateRoom", new Type[1] { typeof(bool) }, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(BiomeBaseActivateRoomPatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(LocationManager), "PlaceStructures", (Type[])null, (Type[])null), new HarmonyMethod(typeof(LocationPlaceStructuresPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(DataManager), "DeactivateWoolhavenDLC", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(WoolhavenDeactivationPatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(DLCLandController), "CombineColliders", new Type[3] { typeof(Vector2[]), typeof(PolygonCollider2D), typeof(int) }, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(DLCLandCombineCollidersPatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(PlacementRegion), "CreateFloodFill", (Type[])null, (Type[])null), new HarmonyMethod(typeof(PlacementRegionCreateFloodFillPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(SaveAndLoad), "ResetSave", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SaveAndLoadResetPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(SaveAndLoad), "DeleteSaveSlot", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(SaveAndLoadDeletePatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(LocationManager), "PlaceStructure", new Type[2] { typeof(StructuresData), typeof(GameObject) }, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(RemoteBuildStationPlacePatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(UIBuildMenuController), "Awake", (Type[])null, (Type[])null), new HarmonyMethod(typeof(RemoteBuildStationMenuPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(StructuresData), "LocalizedName", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(RemoteBuildStationNamePatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(StructuresData), "LocalizedDescription", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(RemoteBuildStationDescriptionPatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); StructureManager.OnStructuresPlaced = (StructuresPlaced)Delegate.Combine((Delegate?)(object)StructureManager.OnStructuresPlaced, (Delegate?)new StructuresPlaced(EvenMoreSpaceState.ScheduleDelayedVisualRepair)); StructureManager.OnStructuresPlaced = (StructuresPlaced)Delegate.Combine((Delegate?)(object)StructureManager.OnStructuresPlaced, (Delegate?)new StructuresPlaced(BuildModePerformanceState.MarkGridDirty)); StructureManager.OnStructureAddedToGrid = (StructureChanged)Delegate.Combine((Delegate?)(object)StructureManager.OnStructureAddedToGrid, (Delegate?)new StructureChanged(BuildModePerformanceState.MarkGridDirty)); StructureManager.OnStructureMoved = (StructureChanged)Delegate.Combine((Delegate?)(object)StructureManager.OnStructureMoved, (Delegate?)new StructureChanged(BuildModePerformanceState.MarkGridDirty)); StructureManager.OnStructureRemoved = (StructureChanged)Delegate.Combine((Delegate?)(object)StructureManager.OnStructureRemoved, (Delegate?)new StructureChanged(BuildModePerformanceState.MarkGridDirty)); Log.LogInfo((object)("EvenMoreSpace loaded with the " + 20 + "-plot preset.")); RefreshExpansionRuntimePatches(); } private void Update() { if (!(Time.unscaledTime < _nextRuntimePatchCheck)) { _nextRuntimePatchCheck = Time.unscaledTime + 0.5f; RefreshExpansionRuntimePatches(); BuildModePerformanceState.CleanupInterruptedOverlay(); EvenMoreSpaceState.RefreshExpansionTrigger(); } } internal void RefreshExpansionRuntimePatches() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown //IL_00da: Expected O, but got Unknown //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected O, but got Unknown //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Expected O, but got Unknown //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Expected O, but got Unknown //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Expected O, but got Unknown //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Expected O, but got Unknown //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Expected O, but got Unknown //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Expected O, but got Unknown //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Expected O, but got Unknown //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Expected O, but got Unknown //IL_0347: Expected O, but got Unknown //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Expected O, but got Unknown //IL_03ad: Unknown result type (might be due to invalid IL or missing references) //IL_03bb: Expected O, but got Unknown bool flag = EvenMoreSpaceState.HasActiveExpansion(); if (flag != _expansionRuntimePatchesInstalled && HarmonyInstance != null) { if (flag) { HarmonyInstance.Patch((MethodBase)AccessTools.PropertyGetter(typeof(PlacementRegion), "X_Constraints"), (HarmonyMethod)null, new HarmonyMethod(typeof(PlacementRegionConstraintsPatch), "XPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.PropertyGetter(typeof(PlacementRegion), "Y_Constraints"), (HarmonyMethod)null, new HarmonyMethod(typeof(PlacementRegionConstraintsPatch), "YPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(Structures_Ranch), "GetRanchingTiles", (Type[])null, (Type[])null), new HarmonyMethod(typeof(RanchTileScanPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(RanchTileScanPatch), "Finalizer", (Type[])null), (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(Structures_Ranch), "GetValidRanchingTiles", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(RanchInnerScanPatch), "Transpiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(Structures_Ranch), "WillHitFence", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(RanchInnerScanPatch), "Transpiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(Interaction_Ranch), "CheckValidEnclosure", new Type[1] { typeof(StructuresData) }, (Type[])null), new HarmonyMethod(typeof(RanchValidationPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(Interaction_Ranch), "UpdateAllFences", (Type[])null, (Type[])null), new HarmonyMethod(typeof(RanchFenceRefreshPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(PlacementRegion), "UpdateFenceablePositions", (Type[])null, (Type[])null), new HarmonyMethod(typeof(RanchFencePlacementPositionsPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(PlacementRegion), "PlaceTiles", (Type[])null, (Type[])null), new HarmonyMethod(typeof(BuildModePlaceTilesPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(PlacementRegion), "GetTile", new Type[1] { typeof(Vector3) }, (Type[])null), new HarmonyMethod(typeof(BuildModeGetTilePatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(PlacementRegion), "GetClosestTileAtWorldPosition", new Type[2] { typeof(Vector3), typeof(float) }, (Type[])null), new HarmonyMethod(typeof(BuildModeGetClosestTilePatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); PatchBuildMouseRuntimeMethods(); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(PlacementRegion), "UpdateTileAvailability", (Type[])null, (Type[])null), new HarmonyMethod(typeof(BuildModeTileAvailabilityPatch), "Prefix", (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(BuildModeTileAvailabilityPatch), "Transpiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(PlacementRegion), "ClearTilesIE", (Type[])null, (Type[])null), new HarmonyMethod(typeof(BuildModeClearTilesPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeof(PlacementRegion), "OnDestroy", (Type[])null, (Type[])null), new HarmonyMethod(typeof(BuildModeRegionDestroyPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); PatchResourceTaskRuntimeMethods(); Log.LogInfo((object)"Enabled expanded-map build and ranch patches for an active extra-land save."); } else { UnpatchExpansionRuntimeMethods(); RanchPerformanceState.Reset(); BuildModePerformanceState.Reset(); Log.LogInfo((object)"Disabled expanded-map build and ranch patches because this save has no active extra land."); } _expansionRuntimePatchesInstalled = flag; } } private void PatchResourceTaskRuntimeMethods() { //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected O, but got Unknown //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Expected O, but got Unknown //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Expected O, but got Unknown MethodBase methodBase = AccessTools.Method(typeof(Structures_Tree), "GetAvailableTasks", (Type[])null, (Type[])null); MethodBase methodBase2 = AccessTools.Method(typeof(Structures_Rubble), "GetAvailableTasks", (Type[])null, (Type[])null); MethodBase methodBase3 = AccessTools.Method(typeof(FollowerTask_ChopTrees), "OnDoingBegin", new Type[1] { typeof(Follower) }, (Type[])null); MethodBase methodBase4 = AccessTools.Method(typeof(FollowerTask_ClearRubble), "OnDoingBegin", new Type[1] { typeof(Follower) }, (Type[])null); MethodBase methodBase5 = AccessTools.Method(typeof(FollowerTask_ClearRubble), "UpdateDestination", new Type[1] { typeof(Follower) }, (Type[])null); try { if (methodBase != null) { HarmonyInstance.Patch(methodBase, new HarmonyMethod(typeof(ExpandedTreeTasksPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (methodBase2 != null) { HarmonyInstance.Patch(methodBase2, new HarmonyMethod(typeof(ExpandedRubbleTasksPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (methodBase3 != null) { HarmonyInstance.Patch(methodBase3, new HarmonyMethod(typeof(ExpandedChopTaskPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (methodBase4 != null) { HarmonyInstance.Patch(methodBase4, new HarmonyMethod(typeof(ExpandedRubbleTaskPatch), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } if (methodBase5 != null) { HarmonyInstance.Patch(methodBase5, (HarmonyMethod)null, new HarmonyMethod(typeof(ExpandedRubbleDestinationPatch), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } catch (Exception ex) { UnpatchRuntimeMethod(methodBase); UnpatchRuntimeMethod(methodBase2); UnpatchRuntimeMethod(methodBase3); UnpatchRuntimeMethod(methodBase4); UnpatchRuntimeMethod(methodBase5); Log.LogError((object)("Could not install expanded resource-task guards; they were disabled for this session: " + ex.Message)); } } private void PatchBuildMouseRuntimeMethods() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown MethodBase placementEnumeratorMoveNext = GetPlacementEnumeratorMoveNext("PlaceObject"); MethodBase placementEnumeratorMoveNext2 = GetPlacementEnumeratorMoveNext("PlaceObject_o"); HarmonyMethod val = new HarmonyMethod(typeof(BuildModeMouseCameraGatePatch), "Transpiler", (Type[])null); if (placementEnumeratorMoveNext != null) { HarmonyInstance.Patch(placementEnumeratorMoveNext, (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null); } if (placementEnumeratorMoveNext2 != null) { HarmonyInstance.Patch(placementEnumeratorMoveNext2, (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null); } } private static MethodBase GetPlacementEnumeratorMoveNext(string methodName) { MethodBase methodBase = AccessTools.Method(typeof(PlacementRegion), methodName, (Type[])null, (Type[])null); if (!(methodBase != null)) { return null; } return AccessTools.EnumeratorMoveNext(methodBase); } private void UnpatchExpansionRuntimeMethods() { UnpatchRuntimeMethod(AccessTools.PropertyGetter(typeof(PlacementRegion), "X_Constraints")); UnpatchRuntimeMethod(AccessTools.PropertyGetter(typeof(PlacementRegion), "Y_Constraints")); UnpatchRuntimeMethod(AccessTools.Method(typeof(Structures_Ranch), "GetRanchingTiles", (Type[])null, (Type[])null)); UnpatchRuntimeMethod(AccessTools.Method(typeof(Structures_Ranch), "GetValidRanchingTiles", (Type[])null, (Type[])null)); UnpatchRuntimeMethod(AccessTools.Method(typeof(Structures_Ranch), "WillHitFence", (Type[])null, (Type[])null)); UnpatchRuntimeMethod(AccessTools.Method(typeof(Interaction_Ranch), "CheckValidEnclosure", new Type[1] { typeof(StructuresData) }, (Type[])null)); UnpatchRuntimeMethod(AccessTools.Method(typeof(Interaction_Ranch), "UpdateAllFences", (Type[])null, (Type[])null)); UnpatchRuntimeMethod(AccessTools.Method(typeof(PlacementRegion), "UpdateFenceablePositions", (Type[])null, (Type[])null)); UnpatchRuntimeMethod(AccessTools.Method(typeof(PlacementRegion), "PlaceTiles", (Type[])null, (Type[])null)); UnpatchRuntimeMethod(AccessTools.Method(typeof(PlacementRegion), "GetTile", new Type[1] { typeof(Vector3) }, (Type[])null)); UnpatchRuntimeMethod(AccessTools.Method(typeof(PlacementRegion), "GetClosestTileAtWorldPosition", new Type[2] { typeof(Vector3), typeof(float) }, (Type[])null)); UnpatchRuntimeMethod(GetPlacementEnumeratorMoveNext("PlaceObject")); UnpatchRuntimeMethod(GetPlacementEnumeratorMoveNext("PlaceObject_o")); UnpatchRuntimeMethod(AccessTools.Method(typeof(PlacementRegion), "UpdateTileAvailability", (Type[])null, (Type[])null)); UnpatchRuntimeMethod(AccessTools.Method(typeof(PlacementRegion), "ClearTilesIE", (Type[])null, (Type[])null)); UnpatchRuntimeMethod(AccessTools.Method(typeof(PlacementRegion), "OnDestroy", (Type[])null, (Type[])null)); UnpatchRuntimeMethod(AccessTools.Method(typeof(Structures_Tree), "GetAvailableTasks", (Type[])null, (Type[])null)); UnpatchRuntimeMethod(AccessTools.Method(typeof(Structures_Rubble), "GetAvailableTasks", (Type[])null, (Type[])null)); UnpatchRuntimeMethod(AccessTools.Method(typeof(FollowerTask_ChopTrees), "OnDoingBegin", new Type[1] { typeof(Follower) }, (Type[])null)); UnpatchRuntimeMethod(AccessTools.Method(typeof(FollowerTask_ClearRubble), "OnDoingBegin", new Type[1] { typeof(Follower) }, (Type[])null)); UnpatchRuntimeMethod(AccessTools.Method(typeof(FollowerTask_ClearRubble), "UpdateDestination", new Type[1] { typeof(Follower) }, (Type[])null)); } private void UnpatchRuntimeMethod(MethodBase method) { if (method != null && HarmonyInstance != null) { HarmonyInstance.Unpatch(method, (HarmonyPatchType)0, "com.cotl.evenmorespace"); } } private void OnDestroy() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown StructureManager.OnStructuresPlaced = (StructuresPlaced)Delegate.Remove((Delegate?)(object)StructureManager.OnStructuresPlaced, (Delegate?)new StructuresPlaced(EvenMoreSpaceState.ScheduleDelayedVisualRepair)); StructureManager.OnStructuresPlaced = (StructuresPlaced)Delegate.Remove((Delegate?)(object)StructureManager.OnStructuresPlaced, (Delegate?)new StructuresPlaced(BuildModePerformanceState.MarkGridDirty)); StructureManager.OnStructureAddedToGrid = (StructureChanged)Delegate.Remove((Delegate?)(object)StructureManager.OnStructureAddedToGrid, (Delegate?)new StructureChanged(BuildModePerformanceState.MarkGridDirty)); StructureManager.OnStructureMoved = (StructureChanged)Delegate.Remove((Delegate?)(object)StructureManager.OnStructureMoved, (Delegate?)new StructureChanged(BuildModePerformanceState.MarkGridDirty)); StructureManager.OnStructureRemoved = (StructureChanged)Delegate.Remove((Delegate?)(object)StructureManager.OnStructureRemoved, (Delegate?)new StructureChanged(BuildModePerformanceState.MarkGridDirty)); if (_expansionRuntimePatchesInstalled) { UnpatchExpansionRuntimeMethods(); _expansionRuntimePatchesInstalled = false; } RanchPerformanceState.Reset(); BuildModePerformanceState.Reset(); EvenMoreSpaceState.ReleaseTransientDlcFreePresentation(); if (HarmonyInstance != null) { HarmonyInstance.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } } internal static class EvenMoreSpaceConfig { internal const int PresetPlotLimit = 20; internal const int PresetStepLimit = 60; internal const int PresetMinimumTileCap = 40000; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<int> MaxExtraSteps; internal static ConfigEntry<int> MinimumTileCap; internal static ConfigEntry<int> ExtraSegmentWeedCount; internal static ConfigEntry<bool> CreateGroundVisuals; internal static ConfigEntry<bool> ClearConnectorScenery; internal static ConfigEntry<bool> DuplicateConnectorBridge; internal static ConfigEntry<bool> DuplicateBackgroundDecor; internal static ConfigEntry<int> MaxVisualClones; internal static ConfigEntry<bool> UseVanillaMoleCost; internal static ConfigEntry<int> ExtraMoleCost; internal static ConfigEntry<int> CostIncreasePerCompletedRow; internal static ConfigEntry<bool> EnableRemoteBuildStation; internal static ConfigEntry<int> RanchEnclosureScanLimit; internal static ConfigEntry<bool> OptimizeExpandedBuildMode; internal static ConfigEntry<int> BuildTileWindowRadius; internal static ConfigEntry<bool> DebugLogging; internal static void Bind(ConfigFile config) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Expected O, but got Unknown //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Expected O, but got Unknown //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Expected O, but got Unknown //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Expected O, but got Unknown //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Expected O, but got Unknown Enabled = config.Bind<bool>("General", "Enabled", true, "Enable extra Woolhaven base expansion."); MaxExtraSteps = config.Bind<int>("Expansion", "MaxExtraSteps", 60, new ConfigDescription("Maximum extra mole purchases for the installed " + 20 + "-plot edition. Each three purchases add one complete plot row.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 60), new object[0])); MinimumTileCap = config.Bind<int>("Safety", "MinimumTileCap", 40000, new ConfigDescription("Maximum iterative placement-grid tiles available to an expanded base. The installed plot edition enforces its own safe minimum.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(5000, 250000), new object[0])); ExtraSegmentWeedCount = config.Bind<int>("Population", "ExtraSegmentWeedCount", 36, new ConfigDescription("Target weed count for each new center segment; side segments use 75 percent. Existing populated segments are not changed.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 150), new object[0])); CreateGroundVisuals = config.Bind<bool>("Visuals", "CreateGroundVisuals", true, "Extend Woolhaven's own SpriteShape fill and border over purchased extra segments."); ClearConnectorScenery = config.Bind<bool>("Visuals", "ClearConnectorScenery", true, "Hide named trees, walls, bushes, and tall grass where generated center connectors open."); DuplicateConnectorBridge = config.Bind<bool>("Visuals", "DuplicateConnectorBridge", true, "Add a filtered set of vanilla SHOW DLC wall-cap sprites around each generated center walkway."); DuplicateBackgroundDecor = config.Bind<bool>("Visuals", "DuplicateBackgroundDecor", false, "Experimental collision-free scenery copies. Disabled by default so Woolhaven's existing fog/weather remains uncluttered."); MaxVisualClones = config.Bind<int>("Visuals", "MaxVisualClones", 48, new ConfigDescription("Maximum cloned land visual objects to create.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 160), new object[0])); UseVanillaMoleCost = config.Bind<bool>("Mole Trigger", "UseVanillaMoleCost", true, "Use the final vanilla mole's resource cost for extra expansions."); ExtraMoleCost = config.Bind<int>("Mole Trigger", "ExtraMoleCost", 150, new ConfigDescription("Resource cost when UseVanillaMoleCost is false.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10000), new object[0])); CostIncreasePerCompletedRow = config.Bind<int>("Mole Trigger", "CostIncreasePerCompletedRow", 25, new ConfigDescription("Amount added to each plot price after every completed three-plot row. Set to 0 for flat pricing.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10000), new object[0])); EnableRemoteBuildStation = config.Bind<bool>("Remote Build Station", "Enabled", true, "Turn Woolhaven Small Statue 2 into a placeable Remote Construction Totem that opens the normal build menu."); RanchEnclosureScanLimit = config.Bind<int>("Performance", "RanchEnclosureScanLimit", 128, new ConfigDescription("Maximum horizontal or vertical tiles checked by Woolhaven ranch enclosure searches while extra land is active.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(64, 512), new object[0])); OptimizeExpandedBuildMode = config.Bind<bool>("Performance", "OptimizeExpandedBuildMode", true, "Use a moving window of placement overlay tiles instead of creating and updating one overlay object for every expanded-map tile."); BuildTileWindowRadius = config.Bind<int>("Performance", "BuildTileWindowRadius", 20, new ConfigDescription("Radius of the visible build-overlay window around the placement cursor. Increase only if placement squares disappear at unusually wide camera zooms.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(12, 40), new object[0])); DebugLogging = config.Bind<bool>("Debug", "DebugLogging", false, "Write verbose EvenMoreSpace logs."); } } internal static class BuildModePerformanceState { private sealed class WindowState { internal List<PlacementTile> Tiles; internal readonly Dictionary<Vector2Int, PlacementTile> Lookup = new Dictionary<Vector2Int, PlacementTile>(); internal Vector2Int Center; internal bool Initialized; internal int WindowVersion; internal int LastGridRevision = -1; internal int LastWindowVersion = -1; internal Vector2Int LastAvailabilityPosition; internal TYPES LastStructureType; internal bool HasAvailabilityPosition; } private sealed class GridPositionMembershipState { internal int Revision; internal int Count; internal HashSet<Vector2Int> Positions; } private static readonly FieldInfo TilesField = AccessTools.Field(typeof(PlacementRegion), "Tiles"); private static readonly FieldInfo TilesInitiatedField = AccessTools.Field(typeof(PlacementRegion), "tilesInitiated"); private static readonly FieldInfo PlacementObjectField = AccessTools.Field(typeof(PlacementRegion), "placementObject"); private static readonly FieldInfo CurrentTileField = AccessTools.Field(typeof(PlacementRegion), "CurrentTile"); private static readonly FieldInfo IsClearingTilesField = AccessTools.Field(typeof(PlacementRegion), "isClearingTiles"); private static readonly MethodInfo GetFromPoolMethod = AccessTools.Method(typeof(PlacementRegion), "GetFromPool", new Type[1] { typeof(GameObject) }, (Type[])null); private static readonly MethodInfo ReturnToPoolMethod = AccessTools.Method(typeof(PlacementRegion), "ReturnToPool", new Type[1] { typeof(GameObject) }, (Type[])null); private static readonly MethodInfo OnStructuresPlacedMethod = AccessTools.Method(typeof(PlacementRegion), "OnStructuresPlaced", (Type[])null, (Type[])null); private static readonly Dictionary<int, WindowState> Windows = new Dictionary<int, WindowState>(); private static readonly Dictionary<List<Vector2Int>, GridPositionMembershipState> GridPositionMembership = new Dictionary<List<Vector2Int>, GridPositionMembershipState>(); private static int _gridRevision; internal static bool IsSupported { get { if (TilesField != null && TilesInitiatedField != null && PlacementObjectField != null && CurrentTileField != null && IsClearingTilesField != null && GetFromPoolMethod != null && ReturnToPoolMethod != null) { return OnStructuresPlacedMethod != null; } return false; } } internal static bool ShouldOptimize(PlacementRegion region) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 if ((Object)(object)region != (Object)null && IsSupported && EvenMoreSpaceConfig.OptimizeExpandedBuildMode.Value && EvenMoreSpaceState.HasActiveExpansion() && (int)region.StructureType != 393 && (Object)(object)region.PlacementSquare != (Object)null && region.Grid != null) { return region.Grid.Count > 0; } return false; } internal static void MarkGridDirty() { _gridRevision++; GridPositionMembership.Clear(); } internal static void MarkGridDirty(StructuresData structure) { _gridRevision++; GridPositionMembership.Clear(); } internal static void ForgetRegion(PlacementRegion region) { if ((Object)(object)region != (Object)null) { ForceCleanupRegion(region); } } internal static void ClearOptimizedWindowIfPresent(PlacementRegion region) { if ((Object)(object)region != (Object)null && Windows.ContainsKey(((Object)region).GetInstanceID())) { ForceCleanupRegion(region); } } internal static void Reset() { if ((Object)(object)PlacementRegion.Instance != (Object)null && IsSupported) { ForceCleanupRegion(PlacementRegion.Instance); } Windows.Clear(); GridPositionMembership.Clear(); _gridRevision++; } internal static bool ContainsGridPosition(List<Vector2Int> positions, Vector2Int position) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) if (positions == null || positions.Count == 0) { return false; } if (!GridPositionMembership.TryGetValue(positions, out var value) || value == null || value.Revision != _gridRevision || value.Count != positions.Count) { GridPositionMembershipState gridPositionMembershipState = new GridPositionMembershipState(); gridPositionMembershipState.Revision = _gridRevision; gridPositionMembershipState.Count = positions.Count; gridPositionMembershipState.Positions = new HashSet<Vector2Int>(positions); value = gridPositionMembershipState; GridPositionMembership[positions] = value; } return value.Positions.Contains(position); } internal static void CleanupInterruptedOverlay() { PlacementRegion instance = PlacementRegion.Instance; if ((Object)(object)instance == (Object)null || !IsSupported || !EvenMoreSpaceState.HasActiveExpansion()) { return; } bool flag = (bool)TilesInitiatedField.GetValue(instance); object? value = PlacementObjectField.GetValue(instance); PlacementObject val = (PlacementObject)((value is PlacementObject) ? value : null); bool flag2 = Windows.ContainsKey(((Object)instance).GetInstanceID()); PlacementTile[] componentsInChildren = ((Component)instance).GetComponentsInChildren<PlacementTile>(true); bool flag3 = false; for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null && ((Component)componentsInChildren[i]).gameObject.activeSelf) { flag3 = true; break; } } if ((Object)(object)val == (Object)null && (flag2 || flag || flag3)) { ForceCleanupRegion(instance); } } internal unsafe static IEnumerator PlaceTilesWindow(PlacementRegion region) { if ((Object)(object)region == (Object)null || !IsSupported) { yield break; } if ((bool)TilesInitiatedField.GetValue(region)) { if (!Windows.TryGetValue(((Object)region).GetInstanceID(), out var value) || value == null || !value.Initialized || IsWindowHealthy(region, value)) { yield break; } ForceCleanupRegion(region); } if (TilesField.GetValue(region) is List<PlacementTile> { Count: >0 } list) { ReleasePlacementTiles(region, list); list.Clear(); } TilesInitiatedField.SetValue(region, true); List<PlacementTile> list2 = new List<PlacementTile>(); TilesField.SetValue(region, list2); WindowState windowState = new WindowState(); windowState.Tiles = list2; WindowState windowState2 = windowState; Windows[((Object)region).GetInstanceID()] = windowState2; object? value2 = PlacementObjectField.GetValue(region); PlacementObject val = (PlacementObject)((value2 is PlacementObject) ? value2 : null); Vector3 worldPosition = (((Object)(object)val != (Object)null) ? ((Component)val).transform.position : ((Component)region).transform.position); Vector2Int center = FindClosestGridPosition(region, worldPosition); foreach (Vector2Int item in EnumerateWindowPositions(center, GetWindowRadius())) { if (region.GetTileGridTile(item) != null) { AddPlacementTile(region, windowState2, item); } } windowState2.Center = center; if (windowState2.Tiles.Count == 0) { ForceCleanupRegion(region); EvenMoreSpaceState.DebugLog("Could not create any build overlay tiles for the expanded placement region."); yield break; } windowState2.Initialized = true; windowState2.WindowVersion++; OnStructuresPlacedMethod.Invoke(region, null); EvenMoreSpaceState.DebugLog("Created build overlay window with " + windowState2.Tiles.Count + " tiles around " + ((object)(*(Vector2Int*)(¢er))/*cast due to .constrained prefix*/).ToString() + "."); } internal static bool ShouldUseWindowClear(PlacementRegion region) { if ((Object)(object)region != (Object)null && IsSupported && Windows.TryGetValue(((Object)region).GetInstanceID(), out var value) && value != null) { return value.Initialized; } return false; } internal static IEnumerator ClearTilesWindow(PlacementRegion region) { if ((bool)IsClearingTilesField.GetValue(region)) { while ((Object)(object)region != (Object)null && (bool)IsClearingTilesField.GetValue(region)) { yield return null; } yield break; } IsClearingTilesField.SetValue(region, true); try { if (TilesField.GetValue(region) is List<PlacementTile> list) { ReleasePlacementTiles(region, new List<PlacementTile>(list)); list.Clear(); } } finally { ForceCleanupRegion(region); } } internal static bool TryGetTile(PlacementRegion region, Vector3 position, out PlacementTile tile) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) tile = null; if (!EnsureWindow(region, out var state)) { return false; } int num = Mathf.RoundToInt(position.x); int num2 = Mathf.RoundToInt(position.y); if (Mathf.Abs(position.x - (float)num) > 0.001f || Mathf.Abs(position.y - (float)num2) > 0.001f) { return false; } Vector2Int val = default(Vector2Int); ((Vector2Int)(ref val))..ctor(num, num2); EnsureWindowContains(region, state, val); if (!state.Lookup.TryGetValue(val, out tile) || (Object)(object)tile == (Object)null || !((Component)tile).gameObject.activeSelf) { tile = null; return false; } return true; } internal static bool TryGetClosestTile(PlacementRegion region, Vector3 worldPosition, float maxDistance, out PlacementTile tile) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) tile = null; if (!EnsureWindow(region, out var state)) { return false; } Vector3 val = ((Component)region).transform.InverseTransformPoint(worldPosition); if (!TryFindNearbyGridPosition(region, val, out var result)) { result = FindClosestGridPositionLocal(region, val); } if (region.GetTileGridTile(result) == null) { return false; } Vector3 val2 = new Vector3((float)((Vector2Int)(ref result)).x, (float)((Vector2Int)(ref result)).y) - val; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (maxDistance != -1f && sqrMagnitude >= maxDistance * maxDistance) { return false; } EnsureWindowContains(region, state, result); if (!state.Lookup.TryGetValue(result, out tile) || (Object)(object)tile == (Object)null || !((Component)tile).gameObject.activeSelf) { tile = null; return false; } return true; } internal static void ForceCleanupRegion(PlacementRegion region) { if ((Object)(object)region == (Object)null || !IsSupported) { return; } try { List<PlacementTile> list = TilesField.GetValue(region) as List<PlacementTile>; ReleasePlacementTiles(region, list); list?.Clear(); } catch (Exception ex) { EvenMoreSpaceState.DebugLog("Could not finish build-overlay cleanup: " + ex.Message); } finally { Windows.Remove(((Object)region).GetInstanceID()); TilesInitiatedField.SetValue(region, false); IsClearingTilesField.SetValue(region, false); } } private static void ReleasePlacementTiles(PlacementRegion region, IList<PlacementTile> tiles) { if ((Object)(object)region == (Object)null) { return; } HashSet<PlacementTile> hashSet = new HashSet<PlacementTile>(); if (tiles != null) { for (int i = 0; i < tiles.Count; i++) { if ((Object)(object)tiles[i] != (Object)null) { hashSet.Add(tiles[i]); } } } PlacementTile[] componentsInChildren = ((Component)region).GetComponentsInChildren<PlacementTile>(true); for (int j = 0; j < componentsInChildren.Length; j++) { if ((Object)(object)componentsInChildren[j] != (Object)null && ((Object)((Component)componentsInChildren[j]).gameObject).name != "PathBrushPlusPreview") { hashSet.Add(componentsInChildren[j]); } } foreach (PlacementTile item in hashSet) { if ((Object)(object)item == (Object)null || (Object)(object)((Component)item).gameObject == (Object)null) { continue; } if (((Component)item).gameObject.activeSelf || (Object)(object)((Component)item).transform.parent == (Object)(object)((Component)region).transform) { try { ReturnToPoolMethod.Invoke(region, new object[1] { ((Component)item).gameObject }); } catch (Exception ex) { ((Component)item).gameObject.SetActive(false); EvenMoreSpaceState.DebugLog("Could not return a build preview tile to the pool: " + ex.Message); } } else { ((Component)item).gameObject.SetActive(false); } } } internal static bool ShouldRefreshAvailability(PlacementRegion region) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (!EnsureWindow(region, out var state)) { return true; } object? value = CurrentTileField.GetValue(region); PlacementTile val = (PlacementTile)((value is PlacementTile) ? value : null); if ((Object)(object)val == (Object)null) { return true; } Vector2Int gridPosition = val.GridPosition; if (state.HasAvailabilityPosition && state.LastAvailabilityPosition == gridPosition && state.LastStructureType == region.StructureType && state.LastGridRevision == _gridRevision && state.LastWindowVersion == state.WindowVersion) { return false; } state.HasAvailabilityPosition = true; state.LastAvailabilityPosition = gridPosition; state.LastStructureType = region.StructureType; state.LastGridRevision = _gridRevision; state.LastWindowVersion = state.WindowVersion; return true; } private static bool EnsureWindow(PlacementRegion region, out WindowState state) { state = null; if (!ShouldOptimize(region) || (bool)IsClearingTilesField.GetValue(region) || PlacementObjectField.GetValue(region) == null) { return false; } if (TryGetWindow(region, out state)) { return true; } if ((bool)TilesInitiatedField.GetValue(region)) { return false; } IEnumerator enumerator = PlaceTilesWindow(region); while (enumerator.MoveNext()) { } return TryGetWindow(region, out state); } private static bool TryGetWindow(PlacementRegion region, out WindowState state) { state = null; if (!ShouldOptimize(region) || !(bool)TilesInitiatedField.GetValue(region) || (bool)IsClearingTilesField.GetValue(region) || !Windows.TryGetValue(((Object)region).GetInstanceID(), out state) || !state.Initialized) { return false; } List<PlacementTile> objA = TilesField.GetValue(region) as List<PlacementTile>; if (!object.ReferenceEquals(objA, state.Tiles)) { ForceCleanupRegion(region); state = null; return false; } if (!IsWindowHealthy(region, state)) { ForceCleanupRegion(region); state = null; return false; } return true; } private static bool IsWindowHealthy(PlacementRegion region, WindowState state) { if ((Object)(object)region != (Object)null && state != null && state.Initialized && state.Tiles != null && state.Tiles.Count > 0 && state.Lookup.Count == state.Tiles.Count && (Object)(object)state.Tiles[0] != (Object)null && (Object)(object)((Component)state.Tiles[0]).gameObject != (Object)null) { return ((Component)state.Tiles[0]).gameObject.activeSelf; } return false; } private static void EnsureWindowContains(PlacementRegion region, WindowState state, Vector2Int position) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) int windowRadius = GetWindowRadius(); int num = Mathf.Max(4, windowRadius - 4); if ((Mathf.Abs(((Vector2Int)(ref position)).x - ((Vector2Int)(ref state.Center)).x) <= num && Mathf.Abs(((Vector2Int)(ref position)).y - ((Vector2Int)(ref state.Center)).y) <= num && state.Lookup.ContainsKey(position)) || region.GetTileGridTile(position) == null) { return; } int num2 = ((Vector2Int)(ref position)).x - windowRadius; int num3 = ((Vector2Int)(ref position)).x + windowRadius; int num4 = ((Vector2Int)(ref position)).y - windowRadius; int num5 = ((Vector2Int)(ref position)).y + windowRadius; List<Vector2Int> list = new List<Vector2Int>(); foreach (KeyValuePair<Vector2Int, PlacementTile> item in state.Lookup) { Vector2Int key = item.Key; if (((Vector2Int)(ref key)).x < num2 || ((Vector2Int)(ref key)).x > num3 || ((Vector2Int)(ref key)).y < num4 || ((Vector2Int)(ref key)).y > num5) { list.Add(key); } } for (int i = 0; i < list.Count; i++) { PlacementTile val = state.Lookup[list[i]]; state.Lookup.Remove(list[i]); state.Tiles.Remove(val); ReturnToPoolMethod.Invoke(region, new object[1] { ((Component)val).gameObject }); } foreach (Vector2Int item2 in EnumerateWindowPositions(position, windowRadius)) { if (!state.Lookup.ContainsKey(item2) && region.GetTileGridTile(item2) != null) { AddPlacementTile(region, state, item2); } } state.Center = position; state.WindowVersion++; } private static void AddPlacementTile(PlacementRegion region, WindowState state, Vector2Int position) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)region == (Object)null || state == null || (Object)(object)region.PlacementSquare == (Object)null) { return; } GameObject val; try { object? obj = GetFromPoolMethod.Invoke(region, new object[1] { region.PlacementSquare }); val = (GameObject)((obj is GameObject) ? obj : null); } catch (Exception ex) { EvenMoreSpaceState.DebugLog("Skipped expanded build tile because the placement pool was unavailable: " + ex.Message); return; } if (!((Object)(object)val == (Object)null)) { val.transform.SetParent(((Component)region).transform, false); val.transform.localPosition = new Vector3((float)((Vector2Int)(ref position)).x, (float)((Vector2Int)(ref position)).y); PlacementTile component = val.GetComponent<PlacementTile>(); if ((Object)(object)component == (Object)null) { ReturnToPoolMethod.Invoke(region, new object[1] { val }); return; } component.Position = new Vector3((float)((Vector2Int)(ref position)).x, (float)((Vector2Int)(ref position)).y); component.GridPosition = position; component.SetColor(Color.white, ((Component)component).transform.position); state.Tiles.Add(component); state.Lookup[position] = component; } } private static IEnumerable<Vector2Int> EnumerateWindowPositions(Vector2Int center, int radius) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) for (int y = ((Vector2Int)(ref center)).y - radius; y <= ((Vector2Int)(ref center)).y + radius; y++) { for (int x = ((Vector2Int)(ref center)).x - radius; x <= ((Vector2Int)(ref center)).x + radius; x++) { yield return new Vector2Int(x, y); } } } private static int GetWindowRadius() { return Mathf.Clamp(EvenMoreSpaceConfig.BuildTileWindowRadius.Value, 12, 40); } private static Vector2Int FindClosestGridPosition(PlacementRegion region, Vector3 worldPosition) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) return FindClosestGridPositionLocal(region, ((Component)region).transform.InverseTransformPoint(worldPosition)); } private static bool TryFindNearbyGridPosition(PlacementRegion region, Vector3 localPosition, out Vector2Int result) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) Vector2Int val = default(Vector2Int); ((Vector2Int)(ref val))..ctor(Mathf.RoundToInt(localPosition.x), Mathf.RoundToInt(localPosition.y)); float num = float.MaxValue; result = val; bool result2 = false; Vector2Int val2 = default(Vector2Int); for (int i = -2; i <= 2; i++) { for (int j = -2; j <= 2; j++) { ((Vector2Int)(ref val2))..ctor(((Vector2Int)(ref val)).x + j, ((Vector2Int)(ref val)).y + i); if (region.GetTileGridTile(val2) != null) { Vector3 val3 = new Vector3((float)((Vector2Int)(ref val2)).x, (float)((Vector2Int)(ref val2)).y) - localPosition; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; result = val2; result2 = true; } } } } return result2; } private static Vector2Int FindClosestGridPositionLocal(PlacementRegion region, Vector3 localPosition) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) if (TryFindNearbyGridPosition(region, localPosition, out var result)) { return result; } Vector2Int result2 = Vector2Int.zero; float num = float.MaxValue; foreach (TileGridTile item in region.Grid) { Vector3 val = new Vector3((float)((Vector2Int)(ref item.Position)).x, (float)((Vector2Int)(ref item.Position)).y) - localPosition; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; result2 = item.Position; } } return result2; } } internal static class RanchPerformanceState { internal struct TileScanState { internal int Depth; internal Structures_Ranch Ranch; internal HashSet<TileGridTile> FenceTiles; internal Dictionary<List<TileGridTile>, TileListMembershipState> TileListMembership; } internal sealed class TileListMembershipState { internal int Count; internal HashSet<TileGridTile> Tiles; } private sealed class ValidationThrottleState { internal float SuppressUntil; internal float LastValidationAt = -1f; } [ThreadStatic] private static int _scanDepth; [ThreadStatic] private static Structures_Ranch _scanRanch; [ThreadStatic] private static HashSet<TileGridTile> _scanFenceTiles; [ThreadStatic] private static Dictionary<List<TileGridTile>, TileListMembershipState> _scanTileListMembership; private static readonly Dictionary<int, ValidationThrottleState> PendingValidations = new Dictionary<int, ValidationThrottleState>(); private static readonly MethodInfo UpdateAllFencesMethod = AccessTools.Method(typeof(Interaction_Ranch), "UpdateAllFences", (Type[])null, (Type[])null); private static List<TYPES> _indestructibleRanchStructures; private static Interaction_Ranch _coalescedFenceRefreshExecutor; private static Coroutine _coalescedFenceRefreshCoroutine; private static bool _coalescedFenceRefreshScheduled; private static bool _coalescedFenceRefreshRunning; private static int _coalescedFenceRefreshRequestCount; internal static TileScanState EnterTileScan(Structures_Ranch ranch) { TileScanState result = new TileScanState { Depth = _scanDepth, Ranch = _scanRanch, FenceTiles = _scanFenceTiles, TileListMembership = _scanTileListMembership }; _scanDepth++; _scanRanch = ranch; _scanFenceTiles = new HashSet<TileGridTile>(); _scanTileListMembership = new Dictionary<List<TileGridTile>, TileListMembershipState>(); if (ranch != null && ranch.Fences != null) { for (int i = 0; i < ranch.Fences.Count; i++) { FenceData val = ranch.Fences[i]; if (val != null && val.Tile != null) { _scanFenceTiles.Add(val.Tile); } } } return result; } internal static void ExitTileScan(TileScanState previous) { _scanDepth = previous.Depth; _scanRanch = previous.Ranch; _scanFenceTiles = previous.FenceTiles; _scanTileListMembership = previous.TileListMembership; } internal static List<TYPES> GetIndestructibleRanchStructures() { if (_indestructibleRanchStructures == null) { _indestructibleRanchStructures = StructureManager.IndestructibleByRanchStructures; } return _indestructibleRanchStructures; } internal static bool ContainsFence(Structures_Ranch ranch, TileGridTile tile) { if (ranch == null || tile == null) { return false; } if (_scanDepth > 0 && _scanRanch == ranch && _scanFenceTiles != null) { return _scanFenceTiles.Contains(tile); } return ranch.ContainsFence(tile); } internal static bool ContainsTile(List<TileGridTile> tiles, TileGridTile tile) { if (_scanDepth <= 0 || _scanTileListMembership == null) { return tiles?.Contains(tile) ?? false; } if (tiles == null) { return false; } if (tiles.Count == 0) { _scanTileListMembership.Remove(tiles); return false; } if (!_scanTileListMembership.TryGetValue(tiles, out var value) || value == null || value.Tiles == null || tiles.Count < value.Count) { TileListMembershipState tileListMembershipState = new TileListMembershipState(); tileListMembershipState.Count = tiles.Count; tileListMembershipState.Tiles = new HashSet<TileGridTile>(tiles); value = tileListMembershipState; _scanTileListMembership[tiles] = value; } else if (tiles.Count > value.Count) { for (int i = value.Count; i < tiles.Count; i++) { if (tiles[i] != null) { value.Tiles.Add(tiles[i]); } } value.Count = tiles.Count; } return value.Tiles.Contains(tile); } internal static void LimitConstraint(ref Vector2 result) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) if (_scanDepth > 0 && EvenMoreSpaceState.HasActiveExpansion()) { int num = Mathf.Clamp(EvenMoreSpaceConfig.RanchEnclosureScanLimit.Value, 64, 512); float num2 = Mathf.Abs(result.x) + Mathf.Abs(result.y); if (!(num2 <= (float)num)) { float num3 = (float)num * 0.5f; result = new Vector2(0f - num3, num3); } } } internal static bool ShouldRunValidation(Interaction_Ranch ranch, StructuresData changedStructure) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ranch == (Object)null || !EvenMoreSpaceState.HasActiveExpansion()) { return true; } if (ranch.Brain == null || ((StructureBrain)ranch.Brain).Data == null) { return true; } int iD = ((StructureBrain)ranch.Brain).Data.ID; if (changedStructure != null && !StructureManager.RanchingStructures.Contains(changedStructure.Type)) { return true; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (!PendingValidations.TryGetValue(iD, out var value) || value == null) { value = new ValidationThrottleState(); PendingValidations[iD] = value; } if (changedStructure != null) { if (realtimeSinceStartup < value.SuppressUntil) { return false; } value.SuppressUntil = realtimeSinceStartup + 2f; value.LastValidationAt = -1f; return true; } if (realtimeSinceStartup < value.SuppressUntil && value.LastValidationAt >= 0f) { return false; } value.LastValidationAt = realtimeSinceStartup; if (realtimeSinceStartup >= value.SuppressUntil) { value.SuppressUntil = realtimeSinceStartup + 2f; } return true; } internal static bool ShouldRunFenceRefresh(Interaction_Ranch ranch) { if (_coalescedFenceRefreshRunning || !EvenMoreSpaceState.HasActiveExpansion() || UpdateAllFencesMethod == null || !HasMultipleActiveRanches()) { return true; } EvenMoreSpacePlugin instance = EvenMoreSpacePlugin.Instance; if ((Object)(object)instance == (Object)null) { return true; } if (IsUsableRanch(ranch)) { _coalescedFenceRefreshExecutor = ranch; } _coalescedFenceRefreshRequestCount++; if (!_coalescedFenceRefreshScheduled) { _coalescedFenceRefreshScheduled = true; _coalescedFenceRefreshCoroutine = ((MonoBehaviour)instance).StartCoroutine(RunCoalescedFenceRefresh()); } return false; } internal static bool RebuildFencePlacementPositions(PlacementRegion region, List<Vector2Int> fenceableGridPositions, List<Vector2Int> touchingRanchGridPositions) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)region == (Object)null || (int)region.StructureType != 393 || !EvenMoreSpaceState.HasActiveExpansion() || fenceableGridPositions == null || touchingRanchGridPositions == null) { return true; } long timestamp = Stopwatch.GetTimestamp(); try { List<Vector2Int> list = new List<Vector2Int>(); List<Vector2Int> list2 = new List<Vector2Int>(); HashSet<Vector2Int> seen = new HashSet<Vector2Int>(); HashSet<Vector2Int> seen2 = new HashSet<Vector2Int>(); List<Structures_Ranch> allStructuresOfType = StructureManager.GetAllStructuresOfType<Structures_Ranch>(); for (int i = 0; i < allStructuresOfType.Count; i++) { Structures_Ranch val = allStructuresOfType[i]; if (val != null) { AddUniqueTilePositions(val.GetRanchTiles(), list, seen); List<TileGridTile> surroundingRanchTiles = val.GetSurroundingRanchTiles(); AddUniqueTilePositions(surroundingRanchTiles, list, seen); AddUniqueTilePositions(surroundingRanchTiles, list2, seen2); } } int num = 0; if (allStructuresOfType.Count > 0) { List<StructureBrain> allStructuresOfType2 = StructureManager.GetAllStructuresOfType((TYPES)393, true, false); num = allStructuresOfType2.Count; for (int j = 0; j < allStructuresOfType2.Count; j++) { StructureBrain val2 = allStructuresOfType2[j]; if (val2 != null && val2.Data != null) { TileGridTile tileGridTile = region.GetTileGridTile(val2.Data.GridTilePosition); AddUniqueTilePosition(tileGridTile, list, seen); if (tileGridTile != null) { Vector2Int position = tileGridTile.Position; AddUniqueTilePosition(region.GetTileGridTile(new Vector2Int(((Vector2Int)(ref position)).x - 1, ((Vector2Int)(ref position)).y)), list, seen); AddUniqueTilePosition(region.GetTileGridTile(new Vector2Int(((Vector2Int)(ref position)).x, ((Vector2Int)(ref position)).y - 1)), list, seen); AddUniqueTilePosition(region.GetTileGridTile(new Vector2Int(((Vector2Int)(ref position)).x, ((Vector2Int)(ref position)).y + 1)), list, seen); AddUniqueTilePosition(region.GetTileGridTile(new Vector2Int(((Vector2Int)(ref position)).x + 1, ((Vector2Int)(ref position)).y)), list, seen); } } } } fenceableGridPositions.Clear(); fenceableGridPositions.AddRange(list); touchingRanchGridPositions.Clear(); touchingRanchGridPositions.AddRange(list2); double num2 = (double)(Stopwatch.GetTimestamp() - timestamp) * 1000.0 / (double)Stopwatch.Frequency; EvenMoreSpaceState.DebugLog("Rebuilt " + list.Count + " fence placement position(s) for " + allStructuresOfType.Count + " ranch(es) and " + num + " fence(s) in " + num2.ToString("0.00") + " ms."); return false; } catch (Exception ex) { if (EvenMoreSpacePlugin.Log != null) { EvenMoreSpacePlugin.Log.LogError((object)("Optimized ranch fence position rebuild failed; using the vanilla calculation: " + ex)); } return true; } } private static void AddUniqueTilePositions(List<TileGridTile> tiles, List<Vector2Int> positions, HashSet<Vector2Int> seen) { if (tiles != null) { for (int i = 0; i < tiles.Count; i++) { AddUniqueTilePosition(tiles[i], positions, seen); } } } private static void AddUniqueTilePosition(TileGridTile tile, List<Vector2Int> positions, HashSet<Vector2Int> seen) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (tile != null && seen.Add(tile.Position)) { positions.Add(tile.Position); } } private static IEnumerator RunCoalescedFenceRefresh() { yield return null; _coalescedFenceRefreshCoroutine = null; _coalescedFenceRefreshScheduled = false; int requestCount = _coalescedFenceRefreshRequestCount; _coalescedFenceRefreshRequestCount = 0; Interaction_Ranch executor = FindFenceRefreshExecutor(); _coalescedFenceRefreshExecutor = null; if ((Object)(object)executor == (Object)null) { EvenMoreSpaceState.DebugLog("Skipped a coalesced ranch fence refresh because the ranch scene unloaded."); yield break; } long startedAt = Stopwatch.GetTimestamp(); _coalescedFenceRefreshRunning = true; try { UpdateAllFencesMethod.Invoke(executor, null); } catch (TargetInvocationException ex) { Exception ex2 = ex.InnerException ?? ex; if (EvenMoreSpacePlugin.Log != null) { EvenMoreSpacePlugin.Log.LogError((object)("Coalesced ranch fence refresh failed: " + ex2)); } } catch (Exception ex3) { if (EvenMoreSpacePlugin.Log != null) { EvenMoreSpacePlugin.Log.LogError((object)("Coalesced ranch fence refresh failed: " + ex3)); } } finally { _coalescedFenceRefreshRunning = false; } double elapsedMilliseconds = (double)(Stopwatch.GetTimestamp() - startedAt) * 1000.0 / (double)Stopwatch.Frequency; EvenMoreSpaceState.DebugLog("Coalesced " + requestCount + " ranch fence refresh request(s) into one pass (" + elapsedMilliseconds.ToString("0.00") + " ms)."); } private static bool HasMultipleActiveRanches() { int num = 0; List<Interaction_Ranch> ranches = Interaction_Ranch.Ranches; if (ranches == null) { return false; } for (int i = 0; i < ranches.Count; i++) { if (IsUsableRanch(ranches[i]) && ++num > 1) { return true; } } return false; } private static Interaction_Ranch FindFenceRefreshExecutor() { if (IsUsableRanch(_coalescedFenceRefreshExecutor)) { return _coalescedFenceRefreshExecutor; } List<Interaction_Ranch> ranches = Interaction_Ranch.Ranches; if (ranches != null) { for (int i = 0; i < ranches.Count; i++) { if (IsUsableRanch(ranches[i])) { return ranches[i]; } } } return null; } private static bool IsUsableRanch(Interaction_Ranch ranch) { if ((Object)(object)ranch != (Object)null && (Object)(object)((Component)ranch).gameObject != (Object)null && ((Component)ranch).gameObject.activeInHierarchy && ranch.Brain != null) { return ((StructureBrain)ranch.Brain).Data != null; } return false; } internal static void Reset() { EvenMoreSpacePlugin instance = EvenMoreSpacePlugin.Instance; if (_coalescedFenceRefreshCoroutine != null && (Object)(object)instance != (Object)null) { ((MonoBehaviour)instance).StopCoroutine(_coalescedFenceRefreshCoroutine); } _coalescedFenceRefreshExecutor = null; _coalescedFenceRefreshCoroutine = null; _coalescedFenceRefreshScheduled = false; _coalescedFenceRefreshRunning = false; _coalescedFenceRefreshRequestCount = 0; PendingValidations.Clear(); } } internal static class EvenMoreSpaceState { private struct SpriteShapePointSnapshot { internal Vector3 Position; internal Vector3 LeftTangent; internal Vector3 RightTangent; internal ShapeTangentMode TangentMode; internal float Height; internal int SpriteIndex; internal bool Corner; } private struct SuppressedGameObjectState { internal GameObject Target; internal bool ActiveSelf; } private const int FallbackVanillaMaxLandIndex = 2; private const int DlcFreePopulationRevision = 1; private const string CloneRootName = "EvenMoreSpace Visual Clones"; private const string GroundRootName = "EvenMoreSpace Ground"; private const string FreeGroundShapeRootName = "EvenMoreSpace DLC-Free Ground Shape"; private const string PersistentMoleName = "EvenMoreSpace Persistent Mole"; private const string FreeExpansionMarkerName = "EvenMoreSpace Base Expansion Cairn"; private const string BackgroundDecorRootName = "EvenMoreSpace Background Decor"; private const string ConnectorBridgeRootName = "EvenMoreSpace Connector Bridges"; private const string WoolhavenHoopRootPrefix = "Hoop_Pillar_Symbol_1"; private const long ClipperScale = 1000L; private const float SegmentJoinOverlap = 0.35f; private const float ConnectorClearWidth = 6f; private const float ConnectorClearHeight = 6f; private const float SuppressedConnectorBorderHeight = 0.01f; private const int MaxFirstConnectorSceneryRenderers = 1024; private const int MaxConnectorSceneryRenderersPerOpening = 128; private static bool _applying; private static bool _finalMoleHandoffScheduled; private static bool _populationBackfillScheduled; private static bool _delayedVisualRepairScheduled; private static bool _dlcFreeMoleHandoffScheduled; private static bool _moleTemplateWarningLogged; private static bool _prematureMoleHandoffRepairLogged; private static bool _hasDlcFreeMoleHandoffPosition; private static Vector3 _dlcFreeMoleHandoffPosition; private static int _extraStepsCacheSaveSlot = int.MinValue; private static int _extraStepsCacheMaximum = -1; private static int _extraStepsCacheValue; private static bool _extraStepsCacheValid; private static bool _majorDlcAuthenticationCacheValid; private static bool _majorDlcAuthenticationCacheValue; private static float _majorDlcAuthenticationCacheExpiresAt; private static int _stepsOverride = -1; private static PolygonCollider2D _lastExpansionCollider; private static Vector2[] _lastAddedSegmentLocalPath; private static Bounds _lastAddedSegmentWorldBounds; private static Interaction_PurchaseLand _persistentMole; private static FreeExpansionInteraction _freeExpansionMarker; private static GameObject _suppressedDlcEntranceBridge; private static GameObject _suppressedBaseExpansionSign; private static int _vanillaBaseMoleCost = -1; private static readonly List<Renderer> HiddenConnectorRenderers = new List<Renderer>(); private static SpriteShapeController _landSpriteShape; private static List<SpriteShapePointSnapshot> _originalSpriteShapePoints; private static Texture2D _freeGroundTexture; private static Sprite _freeGroundSprite; private static Texture2D _freeMarkerTexture; private static Sprite _freeMarkerSprite; private static SpriteShapeController _freeBaseSpriteShape; private static List<SpriteShapePointSnapshot> _originalFreeSpriteShapePoints; private static bool _freeBaseSpriteShapeExpanded; private static int _originalFreeSpriteShapeSortingOrder; private static bool _freeBaseSpriteShapeSortingCaptured; private static GameObject _freeGroundShapeRoot; private static GameObject _groundRoot; private static GameObject _backgroundDecorRoot; private static GameObject _connectorBridgeRoot; private static readonly List<SuppressedGameObjectState> SuppressedDlcFreeScenery = new List<SuppressedGameObjectState>(); internal static readonly FieldInfo LandSlotsField = AccessTools.Field(typeof(DLCLandController), "landSlots"); internal static readonly FieldInfo DLCLandEnabledField = AccessTools.Field(typeof(DLCLandController), "dlcLandEnabled"); internal static readonly FieldInfo DLCLandDisabledField = AccessTools.Field(typeof(DLCLandController), "dlcLandDisabled"); internal static readonly FieldInfo LandIndexField = AccessTools.Field(typeof(Interaction_PurchaseLand), "landIndex"); internal static readonly FieldInfo CostTypeField = AccessTools.Field(typeof(Interaction_PurchaseLand), "costType"); internal static readonly FieldInfo CostField = AccessTools.Field(typeof(Interaction_PurchaseLand), "cost"); internal static readonly FieldInfo SpineField = AccessTools.Field(typeof(Interaction_PurchaseLand), "spine"); internal static readonly FieldInfo IsRevealedField = AccessTools.Field(typeof(Interaction_PurchaseLand), "isRevealed"); internal static readonly FieldInfo IntroConvoField = AccessTools.Field(typeof(Interaction_PurchaseLand), "introConvo"); internal static readonly FieldInfo CameraTargetField = AccessTools.Field(typeof(Interaction_PurchaseLand), "cameraTarget"); internal static readonly FieldInfo PostBuildOffsetField = AccessTools.Field(typeof(Interaction_PurchaseLand), "postBuildOffset"); internal static readonly FieldInfo PlacementCachedColliderPointsField = AccessTools.Field(typeof(PlacementRegion), "cachedColliderPoints"); internal static readonly FieldInfo PlacementCountField = AccessTools.Field(typeof(PlacementRegion), "Count"); internal static readonly FieldInfo OnboardingDlcBridgeField = AccessTools.Field(typeof(Onboarding), "dlcBridge"); internal static readonly FieldInfo OnboardingBaseExpansionSignField = AccessTools.Field(typeof(Onboarding), "baseExpansionSign"); internal static bool LastFloodFillSucceeded { get; private set; } internal static bool LastGeometryExpansionSucceeded { get; private set; } internal static bool IsVanillaBaseExpansionEventActive() { if (!EvenMoreSpaceConfig.Enabled.Value || !IsWoolhavenActive()) { return false; } if (DataManager.Instance.OnboardedBaseExpansion || DataManager.Instance.LandPurchased >= 0) { return true; } int yngyaOffering = DataManager.Instance.YngyaOffering; if (yngyaOffering < 2) { return yngyaOffering < 0; } return true; } private static bool IsWoolhavenActive() { if (DataManager.Instance == null || !DataManager.Instance.MAJOR_DLC) { return false; } int yngyaOffering = DataManager.Instance.YngyaOffering; if (yngyaOffering >= 2 || yngyaOffering < 0) { return true; } if (!HasDlcFreeOrigin()) { if (!DataManager.Instance.OnboardedBaseExpansion) { return DataManager.Instance.LandPurchased >= 0; } return true; } return false; } private static bool IsFullWoolhavenWorldActive() { if (DataManager.Instance != null && DataManager.Instance.MAJOR_DLC) { return DataManager.Instance.YngyaOffering < 0; } return false; } private static string GetDlcFreeOriginKey(int saveSlot) { return "EvenMoreSpace.DlcFreeOrigin.SaveSlot." + GetCanonicalSaveSlot(saveSlot); } private static bool HasDlcFreeOrigin() { return PlayerPrefs.GetInt(GetDlcFreeOriginKey(SaveAndLoad.SAVE_SLOT), 0) == 1; } private static void MarkDlcFreeOrigin() { if (!HasDlcFreeOrigin()) { PlayerPrefs.SetInt(GetDlcFreeOriginKey(SaveAndLoad.SAVE_SLOT), 1); PlayerPrefs.Save(); } } private static bool HasDlcFreeProgressPendingHandoff() { if (IsWoolhavenActive() && GetExtraSteps() > 0 && !IsDlcFreeMoleRoute()) { if (!HasDlcFreeOrigin()) { return DataManager.Instance.LandPurchased < 0; } return true; } return false; } private static bool HasDlcFreeMoleRouteFlag() { return PlayerPrefs.GetInt(GetDlcFreeMoleRouteKey(SaveAndLoad.SAVE_SLOT), 0) == 1; } internal static bool IsDlcFreeMoleRoute() { if (IsWoolhavenActive() && GetExtraSteps() > 0) { return HasDlcFreeMoleRouteFlag(); } return false; } internal static bool IsReadyForExtraExpansion() { if (!EvenMoreSpaceConfig.Enabled.Value || DataManager.Instance == null) { return false; } if (IsDlcFreeMoleRoute()) { return true; } if (!IsVanillaBaseExpansionEventActive()) { return false; } return DataManager.Instance.LandPurchased >= GetVanillaMaxLandIndex(); } internal static bool IsDlcFreeExpansionAvailable() { if (!EvenMoreSpaceConfig.Enabled.Value || DataManager.Instance == null || IsWoolhavenActive()) { return false; } if ((Object)(object)BiomeBaseManager.Instance != (Object)null && (Object)(object)BiomeBaseManager.Instance.Room != (Object)null && BiomeBaseManager.Instance.Room.Pieces != null && BiomeBaseManager.Instance.Room.Pieces.Count > 0) { return (Object)(object)BiomeBaseManager.Instance.Room.Pieces[0] != (Object)null; } return false; } internal static bool UsesDlcFreeCustomGeometry() { if (!IsDlcFreeExpansionAvailable() && !IsDlcFreeMoleRoute()) { return HasDlcFreeProgressPendingHandoff(); } return true; } internal static bool ShouldSuppressVanillaLandSlotActivation() { if (EvenMoreSpaceConfig.Enabled.Value && GetExtraSteps() > 0 && HasDlcFreeOrigin()) { if (!UsesDlcFreeCustomGeometry()) { return HasDlcFreeMoleRouteFlag(); } return true; } return false; } private static bool IsBaseExpansionSceneReady() { if ((Object)(object)BiomeBaseManager.Instance != (Object)null && (Object)(object)BiomeBaseManager.Instance.Room != (Object)null && BiomeBaseManager.Instance.Room.Pieces != null && BiomeBaseManager.Instance.Room.Pieces.Count > 0 && (Object)(object)BiomeBaseManager.Instance.Room.Pieces[0] != (Object)null && (Object)(object)BiomeBaseManager.Instance.Room.Pieces[0].Collider != (Object)null && BiomeBaseManager.Instance.CachedColliderPoints != null && (Object)(object)DLCLandController.Instance != (Object)null) { return GetLandSlots() != null; } return false; } internal static bool EnsureDlcFreeCustomGeometry() { if (!UsesDlcFreeCustomGeometry() || GetExtraSteps() <= 0 || HasActiveExpansion()) { return true; } if (!IsBaseExpansionSceneReady()) { return false; } return ApplyExpansionToCurrentBase(rebuildPlacementGrid: false); } private static bool UsesVanillaDlcGeometry() { if (UsesDlcFreeCustomGeometry()) { return false; } if (!IsReadyForExtraExpansion() || (Object)(object)DLCLandController.Instance == (Object)null) { return false; } LandSlot[] landSlots = GetLandSlots(); if (landSlots != null) { return landSlots.Length > 0; } return false; } private static bool IsExpansionReadyForGeometry() { if (!IsReadyForExtraExpansion()) { return IsDlcFreeExpansionAvailable(); } return true; } internal static bool IsExtraMole(Interaction_PurchaseLand interaction) { if (IsDlcFreeExpansionAvailable() || !IsReadyForExtraExpansion() || (Object)(object)interaction == (Object)null) { return false; } return GetPrivateInt(LandIndexField, interaction, -999) >= GetVanillaMaxLandIndex(); } internal static bool IsFinalVanillaMolePurchase(Interaction_PurchaseLand interaction) { if (!EvenMoreSpaceConfig.Enabled.Value || IsDlcFreeExpansionAvailable() || !IsVanillaBaseExpansionEventActive() || (Object)(object)interaction == (Object)null || DataManager.Instance == null) { return false; } if (!HasAuthenticatedMajorDlc()) { return false; } int vanillaMaxLandIndex = GetVanillaMaxLandIndex(); int privateInt = GetPrivateInt(LandIndexField, interaction, -999); if (privateInt >= vanillaMaxLandIndex) { return DataManager.Instance.LandPurchased == vanillaMaxLandIndex - 1; } return false; } internal static void ScheduleFinalMoleHandoff(Interaction_PurchaseLand interaction) { if (!_finalMoleHandoffScheduled && IsFinalVanillaMolePurchase(interaction) && !((Object)(object)EvenMoreSpacePlugin.Instance == (Object)null)) { _finalMoleHandoffScheduled = true; ((MonoBehaviour)EvenMoreSpacePlugin.Instance).StartCoroutine(FinalMoleHandoff(interaction)); DebugLog("Scheduled final vanilla mole handoff."); } } private static IEnumerator FinalMoleHandoff(Interaction_PurchaseLand original) { int maxVanillaIndex = GetVanillaMaxLandIndex(); while ((Object)(object)original != (Object)null && DataManager.Instance != null && DataManager.Instance.LandPurchased < maxVanillaIndex) { yield return null; } if ((Object)(object)original == (Object)null || DataManager.Instance == null || DataManager.Instance.LandPurchased < maxVanillaIndex) { _finalMoleHandoffScheduled = false; yield break; } GameObject replacement = null; Exception cloneError = null; try { replacement = Object.Instantiate<GameObject>(((Component)original).gameObject, ((Component)original).transform.position, ((Component)original).transform.rotation); ((Object)replacement).name = ((Object)((Component)original).gameObject).name + " EvenMoreSpace"; replacement.SetActive(false); Interaction_PurchaseLand component = replacement.GetComponent<Interaction_PurchaseLand>(); if ((Object)(object)component == (Object)null) { throw new InvalidOperationException("The cloned mole has no purchase-land interaction."); } ((Behaviour)component).enabled = true; ((Interaction)component).Interactable = true; component.ForceShown = false; } catch (Exception ex) { cloneError = ex; } if (cloneError != null || (Object)(object)replacement == (Object)null) { if ((Object)(object)replacement != (Object)null) { Object.Destroy((Object)(object)replacement); } EvenMoreSpacePlugin.Log.LogError((object)("Could not preserve the final Woolhaven mole: " + cloneError)); _finalMoleHandoffScheduled = false; yield break; } while ((Object)(object)original != (Object)null) { yield return null; } yield return null; if ((Object)(object)replacement != (Object)null) { Interaction_PurchaseLand component2 = replacement.GetComponent<Interaction_PurchaseLand>(); ((Object)replacement).name = "EvenMoreSpace Persistent Mole"; replacement.SetActive(true); _persistentMole = component2; KeepFinalMoleAlive(component2); EvenMoreSpacePlugin.Log.LogInfo((object)"Final Woolhaven mole handoff complete; extra land purchases are now available."); } _finalMoleHandoffScheduled = false; } internal static int GetVanillaMaxLandIndex() { LandSlot[] landSlots = GetLandSlots(); if (landSlots != null && landSlots.Length > 0) { return landSlots.Length - 1; } return 2; } internal static LandSlot[] GetLandSlots() { if ((Object)(object)DLCLandController.Instance == (Object)null || LandSlotsField == null) { return null; } return LandSlotsField.GetValue(DLCLandController.Instance) as LandSlot[]; } internal static int GetExtraSteps() { int value = EvenMoreSpaceConfig.MaxExtraSteps.Value; int sAVE_SLOT = SaveAndLoad.SAVE_SLOT; if (_extraStepsCacheValid && _extraStepsCacheSaveSlot == sAVE_SLOT && _extraStepsCacheMaximum == value) { return Mathf.Clamp(_extraStepsCacheValue, 0, value); } string playerPrefsKey = GetPlayerPrefsKey(SaveAndLoad.SAVE_SLOT); int num = PlayerPrefs.GetInt(playerPrefsKey, 0); if (!PlayerPrefs.HasKey(playerPrefsKey) && SaveAndLoad.SAVE_SLOT >= 10) { string legacyPlayerPrefsKey = GetLegacyPlayerPrefsKey(SaveAndLoad.SAVE_SLOT); if (PlayerPrefs.HasKey(legacyPlayerPrefsKey)) { num = PlayerPrefs.GetInt(legacyPlayerPrefsKey, 0); PlayerPrefs.SetInt(playerPrefsKey, num); PlayerPrefs.DeleteKey(legacyPlayerPrefsKey); PlayerPrefs.Save(); } } if (num < 0) { num = 0; } if (num > value) { num = value; } _extraStepsCacheSaveSlot = sAVE_SLOT; _extraStepsCacheMaximum = value; _extraStepsCacheValue = num; _extraStepsCacheValid = true; return num; } internal static void SetExtraSteps(int steps) { int num = Mathf.Clamp(steps, 0, EvenMoreSpaceConfig.MaxExtraSteps.Value); PlayerPrefs.SetInt(GetPlayerPrefsKey(SaveAndLoad.SAVE_SLOT), num); PlayerPrefs.Save(); _extraStepsCacheSaveSlot = SaveAndLoad.SAVE_SLOT; _extraStepsCacheMaximum = EvenMoreSpaceConfig.MaxExtraSteps.Value; _extraStepsCacheValue = num; _extraStepsCacheValid = true; if ((Object)(object)EvenMoreSpacePlugin.Instance != (Object)null) { EvenMoreSpacePlugin.Instance.RefreshExpansionRuntimePatches(); } } internal static int GetEffectiveExtraSteps() { if (_stepsOverride < 0) { return GetExtraSteps(); } return _stepsOverride; } internal static bool HasActiveExpansion() { if (!EvenMoreSpaceConfig.Enabled.Value || GetEffectiveExtraSteps() <= 0) { return false; } if (IsExpansionReadyForGeometry() && LastGeometryExpansionSucceeded) { return (Object)(object)_lastExpansionCollider != (Object)null; } return false; } private static bool HasAuthenticatedMajorDlc() { if (DataManager.Instance == null || !DataManager.Instance.MAJOR_DLC) { return false; } float unscaledTime = Time.unscaledTime; if (!_majorDlcAuthenticationCacheValid || unscaledTime >= _majorDlcAuthenticationCacheExpiresAt) { _majorDlcAuthenticationCacheValue = GameManager.AuthenticateMajorDLC(); _majorDlcAuthenticationCacheExpiresAt = unscaledTime + 2f; _majorDlcAuthenticationCacheValid = true; } return _majorDlcAuthenticationCacheValue; } internal static bool IsAuthenticatedMajorDlc() { return HasAuthenticatedMajorDlc(); } internal static string GetPlayerPrefsKey(int saveSlot) { return "EvenMoreSpace.ExtraSteps.SaveSlot." + GetCanonicalSaveSlot(saveSlot); } private static string GetDlcFreeMoleRouteKey(int saveSlot) { return "EvenMoreSpace.DlcFreeMoleRoute.SaveSlot." + GetCanonicalSaveSlot(saveSlot); } private static void SetDlcFreeMoleRoute(bool enabled) { string dlcFreeMoleRouteKey = GetDlcFreeMoleRouteKey(SaveAndLoad.SAVE_SLOT); if (enabled) { PlayerPrefs.SetInt(dlcFreeMoleRouteKey, 1); } else { PlayerPrefs.DeleteKey(dlcFreeMoleRouteKey); } PlayerPrefs.Save(); } internal static void ClearSaveSlotState(int saveSlot) { int canonicalSaveSlot = GetCanonicalSaveSlot(saveSlot); PlayerPrefs.DeleteKey(GetPlayerPrefsKey(canonicalSaveSlot)); PlayerPrefs.DeleteKey(GetPopulatedStepsKey(canonicalSaveSlot)); PlayerPrefs.DeleteKey(GetPopulationRevisionKey(canonicalSaveSlot)); PlayerPrefs.DeleteKey(GetRightFirstRowsKey(canonicalSaveSlot)); PlayerPrefs.DeleteKey(GetRightFirstRowsHighKey(canonicalSaveSlot)); PlayerPrefs.DeleteKey(GetDlcFreeMoleRouteKey(canonicalSaveSlot)); PlayerPrefs.DeleteKey(GetDlcFreeOriginKey(canonicalSaveSlot)); PlayerPrefs.DeleteKey(GetLegacyPlayerPrefsKey(canonicalSaveSlot + 10)); PlayerPrefs.Save(); _extraStepsCacheValid = false; if ((Object)(object)EvenMoreSpacePlugin.Instance != (Object)null) { EvenMoreSpacePlugin.Instance.RefreshExpansionRuntimePatches(); } DebugLog("Cleared expansion state for save slot " + canonicalSaveSlot + "."); } private static int GetCanonicalSaveSlot(int saveSlot) { if (saveSlot < 10) { return saveSlot; } return saveSlot - 10; } private static string GetLegacyPlayerPrefsKey(int saveSlot) { return "EvenMoreSpace.ExtraSteps.SaveSlot." + saveSlot; } private static string GetPopulatedStepsKey(int saveSlot) { return "EvenMoreSpace.PopulatedSteps.SaveSlot." + GetCanonicalSaveSlot(saveSlot); } private static string GetPopulationRevisionKey(int saveSlot) { return "EvenMoreSpace.PopulationRevision.SaveSlot." + GetCanonicalSaveSlot(saveSlot); } private static string GetRightFirstRowsKey(int saveSlot) { return "EvenMoreSpace.RightFirstRows.SaveSlot." + GetCanonicalSaveSlot(saveSlot); } private static string GetRightFirstRowsHighKey(int saveSlot) { return "EvenMoreSpace.RightFirstRowsHigh.SaveSlot." + GetCanonicalSaveSlot(saveSlot); } private static int GetRightFirstRows() { return PlayerPrefs.GetInt(GetRightFirstRowsKey(SaveAndLoad.SAVE_SLOT), 0); } private static void SetRightFirstRows(int rows) { PlayerPrefs.SetInt(GetRightFirstRowsKey(SaveAndLoad.SAVE_SLOT), rows); PlayerPrefs.Save(); } private static int GetRightFirstRowsHigh() { return PlayerPrefs.GetInt(GetRightFirstRowsHighKey(SaveAndLoad.SAVE_SLOT), 0); } private static void SetRightFirstRowsHigh(int rows) { PlayerPrefs.SetInt(GetRightFirstRowsHighKey(SaveAndLoad.SAVE_SLOT), rows); PlayerPrefs.Save(); } private static bool IsRightFirstRow(int row) { switch (row) { default: return false; case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: case 48: case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: case 58: case 59: return (GetRightFirstRowsHigh() & (1 << row - 30)) != 0; case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: return (GetRightFirstRows() & (1 << row)) != 0; } } private static void SetRightFirstRow(int row, bool rightFirst) { switch (row) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: { int rightFirstRows = GetRightFirstRows(); int num2 = 1 << row; SetRightFirstRows(rightFirst ? (rightFirstRows | num2) : (rightFirstRows & ~num2)); break; } case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: case 48: case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: case 58: case 59: { int rightFirstRowsHigh = GetRightFirstRowsHigh(); int num = 1 << row - 30; SetRightFirstRowsHigh(rightFirst ? (rightFirstRowsHigh | num) : (rightFirstRowsHigh & ~num)); break; } } } private static int GetSegmentIndexForStep(int step, int slotCount) { if (step <= 0 || slotCount < 3) { if (step <= 0 || slotCount <= 0) { return 0; } return (step - 1) % slotCount; } int num = (step - 1) % 3; if (num == 0) { return 0; } bool flag = IsRightFirstRow((step - 1) / 3); if (num != 1) { if (!flag) { return 2; } return 1; } if (!flag) { return 1; } return 2; } private static int GetPopulatedSteps() { return Mathf.Clamp(PlayerPrefs.GetInt(GetPopulatedStepsKey(SaveAndLoad.SAVE_SLOT), 0), 0, GetExtraSteps()); } private static void SetPopulatedSteps(int steps) { PlayerPrefs.SetInt(GetPopulatedStepsKey(SaveAndLoad.SAVE_SLOT), Mathf.Clamp(steps, 0, GetExtraSteps())); PlayerPrefs.Save(); } private static int GetPopulationRevision() { return PlayerPrefs.GetInt(GetPopulationRevisionKey(SaveAndLoad.SAVE_SLOT), 0); } private static void SetPopulationRevision(int revision) { PlayerPrefs.SetInt(GetPopulationRevisionKey(SaveAndLoad.SAVE_SLOT), revision); PlayerPrefs.Save(); } private static void RefreshInteractionRegion(Interaction interaction) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)interaction == (Object)null) { return; } if (Interactor.InteractionRegions != null) { foreach (List<Interaction> value in Interactor.InteractionRegions.Values) { for (int num = value.Count - 1; num >= 0; num--) { if ((Object)(object)value[num] == (Object)(object)interaction) { value.RemoveAt(num); } } } } interaction.Position = ((Component)interaction).transform.position; Interactor.AddToRegion(interaction); } internal static void KeepFinalMoleAlive(Interaction_PurchaseLand interaction) { //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) if (!IsExtraMole(interaction)) { return; } if (GetExtraSteps() >= EvenMoreSpaceConfig.MaxExtraSteps.Value) { HideExtraMole(interaction); return; } Interaction_SimpleConversation val = (Interaction_SimpleConversation)((IntroConvoField != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(false); } SkeletonAnimation val2 = (SkeletonAnimation)((SpineField != null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val2 != (Object)null) { ((Component)val2).gameObject.SetActive(true); SafePlayMoleAnimation(val2, "idle", "idle"); } ((Component)interaction).transform.SetParent((Transform)null, true); if (_hasDlcFreeMoleHandoffPosition) { ((Component)interaction).transform.position = _dlcFreeMoleHandoffPosition; _hasDlcFreeMoleHandoffPosition = false; } else { ((Component)interaction).transform.position = GetNextMolePosition(GetExtraSteps(), ((Component)interaction).transform.position); } ((Interaction)interaction).ActivatorOffset = Vector3.zero; ((Interaction)interaction).ActivateDistance = Mathf.Max(3f, ((Interaction)interaction).ActivateDistance); RefreshInteractionRegion((Interaction)(object)interaction); interaction.ForceShown = true; SetPrivateBool(IsRevealedField, interaction, value: true); ((Interaction)interaction).Interactable = true; UpdateMoleDisplayedCost(interaction, GetExtraSteps()); _persistentMole = interaction; DebugLog("Kept final mole interaction alive for extra expansion."); } private static void HideExtraMole(Interaction_PurchaseLand interaction) { if (!((Object)(object)interaction == (Object)null)) { ((Interaction)interaction).Interactable = false; interaction.ForceShown = false; _persistentMole = interaction; if ((Object)(object)EvenMoreSpacePlugin.Instance != (Object)null) { ((MonoBehaviour)EvenMoreSpacePlugin.Instance).StartCoroutine(DeactivateMoleNextFrame(((Component)interaction).gameObject)); } else { ((Component)interaction).gameObject.SetActive(false); } DebugLog("Hid the expansion mole because the configured plot limit was reached."); } } private static IEnumerator DeactivateMoleNextFrame(GameObject mole) { yield return null; if ((Object)(object)mole != (Object)null && GetExtraSteps() >= EvenMoreSpaceConfig.MaxExtraSteps.Value) { mole.SetActive(false); } } internal static void EnsureExtraMoleExists() { RemoteBuildStationFeature.EnsureUnlocked(); if (IsDlcFreeExpansionAvailable()) { EnsureDlcFreeExpansionMarker(); } else { if (!IsReadyForExtraExpansion() || _finalMoleHandoffScheduled || !IsBaseExpansionSceneReady()) { return; } if (GetExtraSteps() >= EvenMoreSpaceConfig.MaxExtraSteps.Value) { Interaction_PurchaseLand[] array = Resources.FindObjectsOfTypeAll<Interaction_PurchaseLand>(); for (int i = 0; i < array.Length; i++) { if (IsExtraMole(array[i])) { HideExtraMole(array[i]); } } return; } if ((Object)(object)_persistentMole != (Object)null) { KeepFinalMoleAlive(_persistentMole); return; } Interaction_PurchaseLand[] array2 = Resources.FindObjectsOfTypeAll<Interaction_PurchaseLand>(); for (int j = 0; j < array2.Length; j++) { if ((Object)(object)array2[j] != (Object)null && ((Object)((Component)array2[j]).gameObject).name == "EvenMoreSpace Persistent Mole") { _persistentMole = array2[j]; KeepFinalMoleAlive(array2[j]); return; } } LandSlot[] landSlots = GetLandSlots(); if (landSlots == null || landSlots.Length < 2 || landSlots[^2] == null || (Object)(object)landSlots[^2].Land == (O