Decompiled source of EvenMoreSpace v0.3.51

plugins/EvenMoreSpace.dll

Decompiled 5 days ago
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*)(&center))/*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