Decompiled source of EvenMoreSpace v0.3.76

plugins/EvenMoreSpace.dll

Decompiled a month 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.76.0")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyProduct("EvenMoreSpace")]
[assembly: AssemblyCompany("")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyTitle("EvenMoreSpace")]
[assembly: AssemblyDescription("Extra Woolhaven base expansion for Cult of the Lamb.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyVersion("0.3.76.0")]
namespace EvenMoreSpace;

[BepInPlugin("com.cotl.evenmorespace", "EvenMoreSpace", "0.3.76")]
public sealed class EvenMoreSpacePlugin : BaseUnityPlugin
{
	public const string PluginGuid = "com.cotl.evenmorespace";

	public const string PluginName = "EvenMoreSpace";

	public const string PluginVersion = "0.3.76";

	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_0243: 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_02b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c4: Expected O, but got Unknown
		//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fe: Expected O, but got Unknown
		//IL_034c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0359: Expected O, but got Unknown
		//IL_0385: 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_03fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0407: Expected O, but got Unknown
		//IL_0414: Unknown result type (might be due to invalid IL or missing references)
		//IL_041e: Expected O, but got Unknown
		//IL_041e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0428: Expected O, but got Unknown
		//IL_0434: Unknown result type (might be due to invalid IL or missing references)
		//IL_043e: Expected O, but got Unknown
		//IL_043e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0448: Expected O, but got Unknown
		//IL_0454: Unknown result type (might be due to invalid IL or missing references)
		//IL_045e: Expected O, but got Unknown
		//IL_045e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0468: Expected O, but got Unknown
		//IL_0474: Unknown result type (might be due to invalid IL or missing references)
		//IL_047e: Expected O, but got Unknown
		//IL_047e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0488: Expected O, but got Unknown
		//IL_0494: Unknown result type (might be due to invalid IL or missing references)
		//IL_049e: Expected O, but got Unknown
		//IL_049e: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a8: 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(BiomeBaseManager), "CombineDLCRoomColliders", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(BiomeBaseCombineDlcRoomCollidersPatch), "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();
				EvenMoreSpaceState.ResetPlacementGridRepairState();
				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> GenerateVanillaPlotWalls;

	internal static ConfigEntry<bool> GenerateVanillaPlotBackdrop;

	internal static ConfigEntry<bool> MirrorPlotBackdrop;

	internal static ConfigEntry<float> PlotEdgeSmoothing;

	internal static ConfigEntry<bool> ClearPlotInteriorScenery;

	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_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ed: Expected O, but got Unknown
		//IL_0233: Unknown result type (might be due to invalid IL or missing references)
		//IL_023d: Expected O, but got Unknown
		//IL_0265: Unknown result type (might be due to invalid IL or missing references)
		//IL_026f: Expected O, but got Unknown
		//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c0: Expected O, but got Unknown
		//IL_0301: Unknown result type (might be due to invalid IL or missing references)
		//IL_030b: 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.");
		ClearPlotInteriorScenery = config.Bind<bool>("Visuals", "ClearPlotInteriorScenery", true, "Clear scenery that stands on an extra plot, including village background trees and grass the new ground was built over. Connector openings are cleared regardless.");
		ClearConnectorScenery = config.Bind<bool>("Visuals", "ClearConnectorScenery", true, "Hide named trees, walls, bushes, and tall grass where generated center connectors open.");
		GenerateVanillaPlotWalls = config.Bind<bool>("Visuals", "GenerateVanillaPlotWalls", false, "Rebuild Woolhaven's own plot wall and cap sprites around every purchased extra plot. Off in this edition so plots stay open for custom walls.");
		GenerateVanillaPlotBackdrop = config.Bind<bool>("Visuals", "GenerateVanillaPlotBackdrop", true, "Continue the trees and scenery that stand behind a vanilla plot into the space around every purchased extra plot, instead of leaving empty void.");
		MirrorPlotBackdrop = config.Bind<bool>("Visuals", "MirrorPlotBackdrop", true, "When only one side of the base has scenery beside it to copy, reflect that side across the middle of the plots so both flanks of an expanded base are dressed alike.");
		PlotEdgeSmoothing = config.Bind<float>("Visuals", "PlotEdgeSmoothing", 0.35f, "World units of notch closing applied to the expanded boundary. Raise it if the player catches on a plot edge; set 0 to leave the boundary exactly as the union produced it.");
		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 const float StalledTeardownSeconds = 5f;

	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 float _clearingSince;

	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())
		{
			_clearingSince = 0f;
			return;
		}
		if ((bool)IsClearingTilesField.GetValue(instance))
		{
			if (_clearingSince <= 0f)
			{
				_clearingSince = Time.unscaledTime;
			}
			if (Time.unscaledTime - _clearingSince < 5f)
			{
				return;
			}
			EvenMoreSpaceState.DebugLog("A build-overlay teardown stalled; cleaning it up.");
		}
		else
		{
			_clearingSince = 0f;
		}
		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 HiddenConnectorColliderState
	{
		internal Collider2D Collider;

		internal bool Enabled;
	}

	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 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 PlotWallRootName = "EvenMoreSpace Plot Walls";

	private const float PlotBackdropReach = 16f;

	private const int MaxPlotWallClones = 4000;

	private const int BackdropMirrorMargin = 8;

	private const float InteriorBackdropMaxSize = 6f;

	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 float ConnectorApproachWidth = 9f;

	private const float ConnectorApproachHeight = 16f;

	private const float SceneryBaseLift = 0.25f;

	private const float PlotSceneryEdgeReach = 2.5f;

	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 int _placementGridRepairAttempts;

	private static float _nextPlacementGridRepairAt;

	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 _suppressedDlcEntranceBlockingCollider;

	private static bool _suppressedDlcEntranceBlockingColliderActive;

	private static GameObject _suppressedBaseExpansionSign;

	private static int _vanillaBaseMoleCost = -1;

	private static readonly List<Renderer> HiddenConnectorRenderers = new List<Renderer>();

	private static readonly List<HiddenConnectorColliderState> HiddenConnectorColliders = new List<HiddenConnectorColliderState>();

	private static bool _connectorColliderGraphDirty;

	private static Bounds _connectorColliderGraphBounds;

	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 _plotWallRoot;

	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 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 MethodInfo OnboardingDlcBridgeColliderGetter = AccessTools.PropertyGetter(typeof(Onboarding), "DlcBridgeCollider");

	internal static readonly FieldInfo OnboardingBaseExpansionSignField = AccessTools.Field(typeof(Onboarding), "baseExpansionSign");

	internal static readonly FieldInfo GroundValidationColliderField = AccessTools.Field(typeof(BiomeBaseManager), "GroundValidationCollider");

	internal static readonly MethodInfo SetGroundValidationColliderMethod = AccessTools.Method(typeof(BiomeBaseManager), "SetGroundValidationCollider", (Type[])null, (Type[])null);

	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