Decompiled source of BetterBuilderTools v2.0.0

plugins/BetterBuilderTools/BetterBuildBackout.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Lamb.UI;
using Lamb.UI.BuildMenu;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Better Build Backout")]
[assembly: AssemblyProduct("Better Build Backout")]
[assembly: ComVisible(false)]
[assembly: Guid("ce3ea138-0f05-4b72-88a5-e0493434a508")]
[assembly: AssemblyFileVersion("0.1.10.0")]
[assembly: AssemblyVersion("0.1.10.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BetterBuildBackout
{
	[BepInPlugin("com.cotl.betterbuildertools.betterbuildbackout", "Better Build Backout", "0.1.11")]
	public sealed class BetterBuildBackoutPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.cotl.betterbuildertools.betterbuildbackout";

		public const string PluginName = "Better Build Backout";

		public const string PluginVersion = "0.1.11";

		private Harmony _harmony;

		private bool _hasLastChosen;

		private float _lastReopenTime;

		private float _nextAutoCleanupCheck;

		private float _staleSince;

		private bool _sawBuildActivity;

		private bool _reconciledAfterBuild;

		private float _lastBuildActivityAt;

		private bool _preservingCameraForCatalogue;

		private float _suspendAutoCleanupUntil;

		private int _lastCancelFrame = -1;

		private KeyCode _reopenKey;

		private Interaction_PlacementRegion _lastBuilderInteraction;

		private static readonly MethodInfo OpenBuildMenuMethod = AccessTools.Method(typeof(Interaction_PlacementRegion), "OpenBuildMenu", (Type[])null, (Type[])null);

		private static readonly MethodInfo ClearPrefabsMethod = AccessTools.Method(typeof(PlacementRegion), "ClearPrefabs", (Type[])null, (Type[])null);

		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 PlacementUiField = AccessTools.Field(typeof(PlacementRegion), "placementUI");

		private static readonly FieldInfo IsEditingBuildingsField = AccessTools.Field(typeof(PlacementRegion), "isEditingBuildings");

		internal static ManualLogSource Log { get; private set; }

		internal static BetterBuildBackoutPlugin Instance { get; private set; }

		private void Awake()
		{
			//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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			BetterBuildBackoutConfig.Bind(((BaseUnityPlugin)this).Config);
			_reopenKey = ParseKey(BetterBuildBackoutConfig.ReopenKey.Value, (KeyCode)114);
			_harmony = new Harmony("com.cotl.betterbuildertools.betterbuildbackout");
			_harmony.PatchAll(typeof(BetterBuildBackoutPlugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Better Build Backout 0.1.11 loaded.");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			Instance = null;
		}

		internal void RememberChoice(TYPES structureType)
		{
			_hasLastChosen = true;
		}

		internal void RememberBuilderInteraction(Interaction_PlacementRegion interaction)
		{
			if ((Object)(object)interaction != (Object)null)
			{
				_lastBuilderInteraction = interaction;
			}
		}

		internal void QueueReopen()
		{
			if (BetterBuildBackoutConfig.Enabled.Value && _hasLastChosen && BetterBuildBackoutConfig.AutoReopenAfterPlacement.Value && !(Time.unscaledTime - _lastReopenTime < 0.25f))
			{
				_lastReopenTime = Time.unscaledTime;
				((MonoBehaviour)this).StartCoroutine(ReopenRoutine());
			}
		}

		private void Update()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (BetterBuildBackoutConfig.Enabled.Value)
			{
				bool num = IsActiveBuildPlacement();
				if (num)
				{
					_sawBuildActivity = true;
					_staleSince = 0f;
				}
				if (num && Input.GetKeyDown(_reopenKey))
				{
					((MonoBehaviour)this).StartCoroutine(ReopenRoutine());
				}
				if (EditModeTogglePressed())
				{
					_suspendAutoCleanupUntil = Time.unscaledTime + 2.5f;
					_staleSince = 0f;
				}
				if (BetterBuildBackoutConfig.AutoCleanup.Value)
				{
					CheckAutoCleanup();
				}
			}
		}

		internal bool TryHandleCancelBackout()
		{
			if (!BetterBuildBackoutConfig.Enabled.Value || !BetterBuildBackoutConfig.CancelReopensBuildMenu.Value || !IsActiveBuildPlacement())
			{
				return false;
			}
			if ((Object)(object)PlacementRegion.Instance != (Object)null && IsEditBuildingsMode(PlacementRegion.Instance))
			{
				return false;
			}
			if (_lastCancelFrame == Time.frameCount)
			{
				return true;
			}
			_lastCancelFrame = Time.frameCount;
			((MonoBehaviour)this).StartCoroutine(ReopenRoutine());
			return true;
		}

		private IEnumerator ReopenRoutine()
		{
			if (!IsActiveBuildPlacement() || Time.unscaledTime - _lastReopenTime < 0.25f)
			{
				yield break;
			}
			_lastReopenTime = Time.unscaledTime;
			if (!CancelActivePlacementIfNeeded(BetterBuildBackoutConfig.PreserveCameraForCatalogue.Value))
			{
				yield break;
			}
			_preservingCameraForCatalogue = BetterBuildBackoutConfig.PreserveCameraForCatalogue.Value;
			yield return (object)new WaitForSecondsRealtime(BetterBuildBackoutConfig.ReopenDelay.Value);
			if ((Object)(object)_lastBuilderInteraction != (Object)null && OpenBuildMenuMethod != null && OpenBuildMenuMethod.Invoke(_lastBuilderInteraction, null) is IEnumerator enumerator)
			{
				((MonoBehaviour)_lastBuilderInteraction).StartCoroutine(enumerator);
				yield break;
			}
			Log.LogWarning((object)"Could not reopen through Interaction_PlacementRegion; falling back to UIManager.");
			if ((Object)(object)MonoSingleton<UIManager>.Instance != (Object)null && (Object)(object)MonoSingleton<UIManager>.Instance.BuildMenuTemplate != (Object)null)
			{
				Time.timeScale = 0f;
				MonoSingleton<UIManager>.Instance.ShowBuildMenu((TYPES)0);
			}
		}

		internal void MarkBuildMenuSelection()
		{
			_preservingCameraForCatalogue = false;
		}

		internal void HandleBuildMenuCancel()
		{
			if (_preservingCameraForCatalogue)
			{
				_preservingCameraForCatalogue = false;
				RestoreWorldState(resetCameraToPlayer: true);
			}
		}

		private static bool CancelActivePlacementIfNeeded(bool preserveCamera)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Invalid comparison between Unknown and I4
			PlacementRegion instance = PlacementRegion.Instance;
			if ((Object)(object)instance == (Object)null || (int)instance.CurrentMode == 0)
			{
				return true;
			}
			if ((int)instance.CurrentMode == 4 || (int)instance.CurrentMode == 2)
			{
				Log.LogWarning((object)"Backout ignored while moving/upgrading a structure to avoid losing that edit.");
				return false;
			}
			((MonoBehaviour)instance).StopAllCoroutines();
			GameObject val = (((Object)(object)PlacementObject.Instance != (Object)null) ? ((Component)PlacementObject.Instance).gameObject : null);
			try
			{
				DestroyPlacementTiles(instance);
				ClearPrefabsMethod?.Invoke(instance, null);
				DestroyPrivateObject<PlacementObject>(instance, PlacementObjectField);
				DestroyPrivateObject<PlacementObjectUI>(instance, PlacementUiField);
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Placement cleanup failed: " + ex.Message));
			}
			instance.CurrentMode = (Mode)0;
			instance.PlacementPosition = Vector3.zero;
			TilesInitiatedField?.SetValue(instance, false);
			if ((Object)(object)DLCLandController.Instance != (Object)null)
			{
				DLCLandController.Instance.ShowBridge();
			}
			if ((Object)(object)HUD_Manager.Instance != (Object)null)
			{
				HUD_Manager.Instance.Show(1, false);
				HUD_Manager.Instance.ShowEditMode(false);
			}
			if ((Object)(object)WeatherSystemController.Instance != (Object)null)
			{
				WeatherSystemController.Instance.ShowWeather(false, true);
			}
			if ((Object)(object)LightingManager.Instance != (Object)null)
			{
				LightingManager.Instance.inOverride = false;
				LightingManager.Instance.overrideSettings = null;
				LightingManager.Instance.transitionDurationMultiplier = 0.2f;
				LightingManager.Instance.lerpActive = false;
				LightingManager.Instance.UpdateLighting(true, false, false);
				LightingManager.Instance.PrepareLightingSettings(false);
			}
			if ((Object)(object)GameManager.GetInstance() != (Object)null)
			{
				if ((Object)(object)GameManager.GetInstance().CamFollowTarget != (Object)null)
				{
					((Behaviour)GameManager.GetInstance().CamFollowTarget).enabled = !preserveCamera;
				}
				if ((Object)(object)val != (Object)null)
				{
					GameManager.GetInstance().RemoveFromCamera(val);
				}
				if (!preserveCamera)
				{
					GameManager.GetInstance().RemoveAllFromCamera();
					GameManager.GetInstance().AddPlayerToCamera();
					GameManager.GetInstance().CameraResetTargetZoom();
				}
			}
			GameManager.overridePlayerPosition = false;
			Time.timeScale = 1f;
			return true;
		}

		private void CheckAutoCleanup()
		{
			if (Time.unscaledTime < _suspendAutoCleanupUntil)
			{
				_staleSince = 0f;
			}
			else
			{
				if (Time.unscaledTime < _nextAutoCleanupCheck)
				{
					return;
				}
				_nextAutoCleanupCheck = Time.unscaledTime + 0.25f;
				if (IsActiveBuildPlacement())
				{
					_sawBuildActivity = true;
					_reconciledAfterBuild = false;
					_lastBuildActivityAt = Time.unscaledTime;
					_staleSince = 0f;
					return;
				}
				if (_sawBuildActivity && !_reconciledAfterBuild && !AnyMenuOpen() && Time.unscaledTime - _lastBuildActivityAt >= 0.4f)
				{
					int num = RepairOrphanBuildTiles();
					_reconciledAfterBuild = true;
					if (num > 0)
					{
						Log.LogWarning((object)("Cleared " + num + " orphaned build-grid tile(s) after placement ended."));
					}
				}
				if (!_sawBuildActivity || _preservingCameraForCatalogue || AnyMenuOpen() || !HasStaleBuildSymptoms())
				{
					_staleSince = 0f;
				}
				else if (_staleSince <= 0f)
				{
					_staleSince = Time.unscaledTime;
				}
				else if (!(Time.unscaledTime - _staleSince < BetterBuildBackoutConfig.AutoCleanupDelay.Value))
				{
					RecoverStaleBuildState();
					_sawBuildActivity = false;
					_staleSince = 0f;
					Log.LogInfo((object)"Auto-cleaned stale build placement state.");
				}
			}
		}

		private static void RecoverStaleBuildState()
		{
			PlacementRegion[] array = PlacementRegion.PlacementRegions.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				RecoverPlacementRegion(array[i]);
			}
			if ((Object)(object)PlacementObject.Instance != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)PlacementObject.Instance).gameObject);
			}
			RestoreWorldState(resetCameraToPlayer: true);
			RestorePlayers();
		}

		private static void RecoverPlacementRegion(PlacementRegion region)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)region == (Object)null))
			{
				((MonoBehaviour)region).StopAllCoroutines();
				try
				{
					DestroyPlacementTiles(region);
					DestroyPrivateObject<PlacementObject>(region, PlacementObjectField);
					DestroyPrivateObject<PlacementObjectUI>(region, PlacementUiField);
					ClearPrefabsMethod?.Invoke(region, null);
				}
				catch (Exception ex)
				{
					Log.LogWarning((object)("Auto cleanup placement-region recovery failed: " + ex.Message));
				}
				region.CurrentMode = (Mode)0;
				region.PlacementPosition = Vector3.zero;
				TilesInitiatedField?.SetValue(region, false);
			}
		}

		private static void RestoreWorldState(bool resetCameraToPlayer)
		{
			GameManager.overridePlayerPosition = false;
			Time.timeScale = 1f;
			if ((Object)(object)DLCLandController.Instance != (Object)null)
			{
				DLCLandController.Instance.ShowBridge();
			}
			if ((Object)(object)HUD_Manager.Instance != (Object)null)
			{
				HUD_Manager.Instance.Show(1, false);
				HUD_Manager.Instance.ShowEditMode(false);
			}
			if ((Object)(object)WeatherSystemController.Instance != (Object)null)
			{
				WeatherSystemController.Instance.ShowWeather(false, true);
			}
			if ((Object)(object)LightingManager.Instance != (Object)null)
			{
				LightingManager.Instance.inOverride = false;
				LightingManager.Instance.overrideSettings = null;
				LightingManager.Instance.transitionDurationMultiplier = 0.2f;
				LightingManager.Instance.lerpActive = false;
				LightingManager.Instance.UpdateLighting(true, false, false);
				LightingManager.Instance.PrepareLightingSettings(false);
			}
			if ((Object)(object)GameManager.GetInstance() != (Object)null)
			{
				if ((Object)(object)GameManager.GetInstance().CamFollowTarget != (Object)null)
				{
					((Behaviour)GameManager.GetInstance().CamFollowTarget).enabled = true;
				}
				if (resetCameraToPlayer)
				{
					GameManager.GetInstance().RemoveAllFromCamera();
					GameManager.GetInstance().AddPlayerToCamera();
					GameManager.GetInstance().CameraResetTargetZoom();
				}
			}
		}

		private static void RestorePlayers()
		{
			foreach (PlayerFarming player in PlayerFarming.players)
			{
				if (!((Object)(object)player == (Object)null))
				{
					((Component)player).gameObject.SetActive(true);
					player.GoToAndStopping = false;
					if ((Object)(object)player.state != (Object)null)
					{
						player.state.CURRENT_STATE = (State)0;
					}
					if ((Object)(object)player.interactor != (Object)null)
					{
						player.interactor.CurrentInteraction = null;
						player.interactor.PreviousInteraction = null;
					}
					if ((Object)(object)player.indicator != (Object)null)
					{
						((TMP_Text)player.indicator.text).text = "";
						((TMP_Text)player.indicator.SecondaryText).text = "";
						((TMP_Text)player.indicator.Thirdtext).text = "";
						((TMP_Text)player.indicator.Fourthtext).text = "";
						player.indicator.Reset();
						player.indicator.HideTopInfo();
					}
				}
			}
		}

		private static int RepairOrphanBuildTiles()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Invalid comparison between Unknown and I4
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			if ((int)PlayerFarming.Location != 1 || (Object)(object)PlacementRegion.Instance == (Object)null || PlacementRegion.Instance.Grid == null)
			{
				return 0;
			}
			HashSet<int> hashSet = new HashSet<int>();
			Structure[] array = Structure.Structures.ToArray();
			foreach (Structure val in array)
			{
				if ((Object)(object)val != (Object)null && val.Brain != null && val.Brain.Data != null && (int)val.Brain.Data.Location == 1)
				{
					hashSet.Add(val.Brain.Data.ID);
				}
			}
			int num = 0;
			foreach (TileGridTile item in PlacementRegion.Instance.Grid)
			{
				if (item != null && item.ObjectID >= 0 && !hashSet.Contains(item.ObjectID) && IsBuildSiteTile(item.ObjectOnTile))
				{
					item.Occupied = false;
					item.Obstructed = false;
					item.ReservedForWaste = false;
					item.IsUpgrade = false;
					item.Collapsed = false;
					item.ObjectID = -1;
					item.ObjectOnTile = (TYPES)0;
					num++;
				}
			}
			return num;
		}

		private static bool IsBuildSiteTile(TYPES type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)type != 31)
			{
				return (int)type == 118;
			}
			return true;
		}

		private static void DestroyPlacementTiles(PlacementRegion region)
		{
			if (!(TilesField?.GetValue(region) is List<PlacementTile> list))
			{
				return;
			}
			PlacementTile[] array = list.ToArray();
			foreach (PlacementTile val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
			list.Clear();
		}

		private static void DestroyPrivateObject<T>(PlacementRegion region, FieldInfo field) where T : Component
		{
			object? obj = field?.GetValue(region);
			T val = (T)((obj is T) ? obj : null);
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val).gameObject);
				field.SetValue(region, null);
			}
		}

		private static bool IsActiveBuildPlacement()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Invalid comparison between Unknown and I4
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Invalid comparison between Unknown and I4
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Invalid comparison between Unknown and I4
			PlacementRegion instance = PlacementRegion.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			if (GameManager.IsDungeon(PlayerFarming.Location))
			{
				return false;
			}
			if (IsEditBuildingsMode(instance))
			{
				return true;
			}
			if ((int)instance.CurrentMode == 0)
			{
				return false;
			}
			Mode currentMode = instance.CurrentMode;
			if ((int)currentMode != 1 && (int)currentMode != 5)
			{
				return (int)currentMode == 3;
			}
			return true;
		}

		private static bool IsEditBuildingsMode(PlacementRegion region)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Invalid comparison between Unknown and I4
			if ((Object)(object)region == (Object)null)
			{
				return false;
			}
			if ((int)region.StructureType == 215)
			{
				return true;
			}
			try
			{
				if (IsEditingBuildingsField != null && (bool)IsEditingBuildingsField.GetValue(region))
				{
					return true;
				}
			}
			catch
			{
			}
			return (int)region.CurrentMode == 3;
		}

		private static bool EditModeTogglePressed()
		{
			if (Input.GetKeyDown((KeyCode)99))
			{
				return true;
			}
			try
			{
				return InputManager.UI.GetEditBuildingsButtonDown((PlayerFarming)null);
			}
			catch
			{
				return false;
			}
		}

		private static bool AnyMenuOpen()
		{
			if (UIMenuBase.ActiveMenus != null)
			{
				return UIMenuBase.ActiveMenus.Count > 0;
			}
			return false;
		}

		private static bool HasStaleBuildSymptoms()
		{
			if (GameManager.overridePlayerPosition || Time.timeScale == 0f)
			{
				return true;
			}
			if ((Object)(object)LightingManager.Instance != (Object)null && LightingManager.Instance.inOverride)
			{
				return true;
			}
			if ((Object)(object)PlayerFarming.Instance == (Object)null || (Object)(object)PlayerFarming.Instance.CameraBone == (Object)null || (Object)(object)GameManager.GetInstance() == (Object)null)
			{
				return false;
			}
			return !GameManager.GetInstance().CameraContains(PlayerFarming.Instance.CameraBone);
		}

		private static KeyCode ParseKey(string raw, KeyCode fallback)
		{
			//IL_0011: 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_001a: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return (KeyCode)Enum.Parse(typeof(KeyCode), raw, ignoreCase: true);
			}
			catch
			{
				return fallback;
			}
		}
	}
	[HarmonyPatch(typeof(Interaction_PlacementRegion), "OnInteract")]
	internal static class InteractionPlacementRegionOnInteractPatch
	{
		private static void Prefix(Interaction_PlacementRegion __instance)
		{
			BetterBuildBackoutPlugin.Instance?.RememberBuilderInteraction(__instance);
		}
	}
	internal static class BetterBuildBackoutConfig
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> AutoReopenAfterPlacement;

		internal static ConfigEntry<string> ReopenKey;

		internal static ConfigEntry<float> ReopenDelay;

		internal static ConfigEntry<bool> CancelReopensBuildMenu;

		internal static ConfigEntry<bool> ShowToolPrompt;

		internal static ConfigEntry<bool> AutoCleanup;

		internal static ConfigEntry<float> AutoCleanupDelay;

		internal static ConfigEntry<bool> PreserveCameraForCatalogue;

		internal static void Bind(ConfigFile config)
		{
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Expected O, but got Unknown
			Enabled = config.Bind<bool>("General", "Enabled", true, "Enable Better Build Backout.");
			AutoReopenAfterPlacement = config.Bind<bool>("Build Menu", "ReopenAfterPlacement", false, "Automatically reopen the build catalogue after successfully placing a structure. This is off by default; use ReopenKey for manual return.");
			if (AutoReopenAfterPlacement.Value)
			{
				AutoReopenAfterPlacement.Value = false;
			}
			ReopenKey = config.Bind<string>("Controls", "ReopenKey", "R", "KeyCode used to reopen the build catalogue after placing a structure.");
			ReopenDelay = config.Bind<float>("Build Menu", "ReopenDelay", 0.15f, new ConfigDescription("Delay before reopening the build catalogue.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 1f), Array.Empty<object>()));
			CancelReopensBuildMenu = config.Bind<bool>("Controls", "CancelReopensBuildMenu", true, "When placing a structure, the first UI cancel/back press returns to the build catalogue instead of leaving build mode.");
			AutoCleanup = config.Bind<bool>("Cleanup", "AutoCleanup", true, "Automatically recover stale build tint/camera/player-lock state after leaving build placement.");
			AutoCleanupDelay = config.Bind<float>("Cleanup", "AutoCleanupDelay", 0.75f, new ConfigDescription("Seconds stale build symptoms must persist before auto cleanup runs.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 5f), Array.Empty<object>()));
			PreserveCameraForCatalogue = config.Bind<bool>("Build Menu", "PreserveCameraForCatalogue", true, "Keep the current build camera position when returning to the catalogue for a quick structure swap.");
			ShowToolPrompt = config.Bind<bool>("UI", "ShowToolPrompt", false, "Deprecated. Better Build Backout no longer appends text to the vanilla placement indicator.");
		}
	}
	[HarmonyPatch(typeof(RewiredUIInputSource), "GetCancelButtonDown")]
	internal static class RewiredUICancelButtonDownPatch
	{
		private static void Postfix(ref bool __result)
		{
			if (__result && (Object)(object)BetterBuildBackoutPlugin.Instance != (Object)null && BetterBuildBackoutPlugin.Instance.TryHandleCancelBackout())
			{
				__result = false;
			}
		}
	}
	[HarmonyPatch(typeof(UIBuildMenuController), "ChosenBuilding")]
	internal static class BuildMenuChosenBuildingPatch
	{
		private static void Prefix(TYPES structure)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			BetterBuildBackoutPlugin.Instance?.RememberChoice(structure);
			BetterBuildBackoutPlugin.Instance?.MarkBuildMenuSelection();
		}
	}
	[HarmonyPatch(typeof(UIBuildMenuController), "OnCancelButtonInput")]
	internal static class BuildMenuCancelButtonInputPatch
	{
		private static void Prefix()
		{
			BetterBuildBackoutPlugin.Instance?.HandleBuildMenuCancel();
		}
	}
	[HarmonyPatch(typeof(PlacementRegion), "Play", new Type[] { typeof(Vector3) })]
	internal static class PlacementRegionPlayVectorPatch
	{
		private static void Prefix()
		{
			BetterBuildBackoutPlugin.Instance?.MarkBuildMenuSelection();
		}
	}
	[HarmonyPatch(typeof(PlacementRegion), "Play", new Type[] { typeof(int) })]
	internal static class PlacementRegionPlayIntPatch
	{
		private static void Prefix()
		{
			BetterBuildBackoutPlugin.Instance?.MarkBuildMenuSelection();
		}
	}
	[HarmonyPatch(typeof(PlacementRegion), "Build")]
	internal static class PlacementRegionBuildPatch
	{
		private static void Postfix()
		{
			BetterBuildBackoutPlugin.Instance?.QueueReopen();
		}
	}
}

plugins/BetterBuilderTools/BuildCameraFocus.dll

Decompiled 2 weeks ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Build Camera Focus")]
[assembly: AssemblyProduct("Build Camera Focus")]
[assembly: ComVisible(false)]
[assembly: Guid("8a83b49b-7176-4d1e-8515-dca4b8737746")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BuildCameraFocus
{
	[BepInPlugin("com.cotl.betterbuildertools.buildcamerafocus", "Build Camera Focus", "0.1.0")]
	public sealed class BuildCameraFocusPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.cotl.betterbuildertools.buildcamerafocus";

		public const string PluginName = "Build Camera Focus";

		public const string PluginVersion = "0.1.0";

		private Harmony _harmony;

		internal static ManualLogSource Log { get; private set; }

		internal static BuildCameraFocusPlugin Instance { get; private set; }

		private void Awake()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			BuildCameraFocusConfig.Bind(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("com.cotl.betterbuildertools.buildcamerafocus");
			_harmony.PatchAll(typeof(BuildCameraFocusPlugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Build Camera Focus 0.1.0 loaded.");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			Instance = null;
		}

		internal void Focus(CameraFollowTarget followTarget)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			if (BuildCameraFocusConfig.Enabled.Value && !((Object)(object)followTarget == (Object)null) && !((Object)(object)PlacementObject.Instance == (Object)null))
			{
				Vector3 val = ((Component)PlacementObject.Instance).transform.position + Vector3.back * 0.5f;
				float value = BuildCameraFocusConfig.CameraDistance.Value;
				float num = BuildCameraFocusConfig.CameraAngle.Value * ((float)Math.PI / 180f);
				Vector3 val2 = val + new Vector3(0f, value * Mathf.Sin(num), (0f - value) * Mathf.Cos(num));
				float num2 = 1f - Mathf.Exp((0f - BuildCameraFocusConfig.FollowSharpness.Value) * Time.unscaledDeltaTime);
				Vector3 val3 = Vector3.Lerp(((Component)followTarget).transform.position, val2, num2);
				((Component)followTarget).transform.position = val3;
				((Component)followTarget).transform.rotation = Quaternion.Euler(BuildCameraFocusConfig.CameraAngle.Value, 0f, 0f);
				followTarget.CurrentPosition = val3;
				followTarget.CurrentTargetCameraPosition = val3;
			}
		}
	}
	internal static class BuildCameraFocusConfig
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<float> CameraDistance;

		internal static ConfigEntry<float> CameraAngle;

		internal static ConfigEntry<float> FollowSharpness;

		internal static void Bind(ConfigFile config)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			Enabled = config.Bind<bool>("General", "Enabled", true, "Enable Build Camera Focus.");
			CameraDistance = config.Bind<float>("Camera", "CameraDistance", 11f, new ConfigDescription("Camera distance while following the placement object.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 30f), Array.Empty<object>()));
			CameraAngle = config.Bind<float>("Camera", "CameraAngle", -45f, new ConfigDescription("Camera pitch while following the placement object.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-80f, -15f), Array.Empty<object>()));
			FollowSharpness = config.Bind<float>("Camera", "FollowSharpness", 16f, new ConfigDescription("How quickly the camera follows placement.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 80f), Array.Empty<object>()));
		}
	}
	[HarmonyPatch(typeof(CameraFollowTarget), "LateUpdate")]
	internal static class CameraFollowTargetLateUpdatePatch
	{
		private static void Postfix(CameraFollowTarget __instance)
		{
			BuildCameraFocusPlugin.Instance?.Focus(__instance);
		}
	}
}

plugins/BetterBuilderTools/ClearThisType.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using src.UINavigator;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Clear This Type")]
[assembly: AssemblyProduct("Clear This Type")]
[assembly: ComVisible(false)]
[assembly: Guid("042701eb-e714-4929-96aa-a7f4e71e6630")]
[assembly: AssemblyFileVersion("0.1.7.0")]
[assembly: AssemblyVersion("0.1.7.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ClearThisType
{
	[BepInPlugin("com.cotl.betterbuildertools.clearthistype", "Clear This Type", "0.1.9")]
	public sealed class ClearThisTypePlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.cotl.betterbuildertools.clearthistype";

		public const string PluginName = "Clear This Type";

		public const string PluginVersion = "0.1.9";

		private Harmony _harmony;

		private KeyCode _clearKey;

		private KeyCode _controllerConfirmKey;

		private KeyCode _controllerCancelKey;

		private string _statusText = "";

		private float _statusUntil;

		private TYPES _pendingType;

		private float _pendingUntil;

		private string _pendingName = "";

		private int _pendingCount;

		private GUIStyle _boxStyle;

		private GUIStyle _titleStyle;

		private GUIStyle _bodyStyle;

		private GUIStyle _confirmStyle;

		private GUIStyle _cancelStyle;

		private Texture2D _boxBackground;

		private Texture2D _confirmBackground;

		private Texture2D _cancelBackground;

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ClearThisTypeConfig.Bind(((BaseUnityPlugin)this).Config);
			_clearKey = ParseKey(ClearThisTypeConfig.ClearKey.Value, (KeyCode)289);
			_controllerConfirmKey = ParseKey(ClearThisTypeConfig.ControllerConfirmKey.Value, (KeyCode)330);
			_controllerCancelKey = ParseKey(ClearThisTypeConfig.ControllerCancelKey.Value, (KeyCode)331);
			_harmony = new Harmony("com.cotl.betterbuildertools.clearthistype");
			_harmony.PatchAll(typeof(ClearThisTypePlugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Clear This Type 0.1.9 loaded.");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			DestroyTexture(ref _boxBackground);
			DestroyTexture(ref _confirmBackground);
			DestroyTexture(ref _cancelBackground);
		}

		private void Update()
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			bool allowNearestFallback;
			if (!ClearThisTypeConfig.Enabled.Value || (Object)(object)PlacementRegion.Instance == (Object)null || !IsActiveBuildPlacement())
			{
				ClearPending();
			}
			else if (HasPendingConfirmation() && (Input.GetKeyDown((KeyCode)27) || Input.GetKeyDown((KeyCode)324)))
			{
				ClearPending();
				ShowStatus("Remove all cancelled");
			}
			else if (HasPendingConfirmation() && ControllerCancelPressed())
			{
				ClearPending();
				ShowStatus("Remove all cancelled");
			}
			else if (HasPendingConfirmation() && ControllerConfirmPressed())
			{
				ClearMatchingType(_pendingType);
			}
			else if (ClearPressed(out allowNearestFallback))
			{
				QueueOrClearHoveredType(allowNearestFallback);
			}
		}

		private bool ClearPressed(out bool allowNearestFallback)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			allowNearestFallback = false;
			if (Input.GetKeyDown(_clearKey))
			{
				allowNearestFallback = true;
				return true;
			}
			if (!ClearThisTypeConfig.EnableVanillaClearButton.Value)
			{
				return false;
			}
			try
			{
				return InputManager.Gameplay.GetInteract3ButtonDown(MonoSingleton<UINavigatorNew>.Instance.AllowInputOnlyFromPlayer);
			}
			catch
			{
				return false;
			}
		}

		private bool ControllerConfirmPressed()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(_controllerConfirmKey))
			{
				return true;
			}
			try
			{
				return InputManager.UI.GetAcceptButtonDown((PlayerFarming)null);
			}
			catch
			{
				return false;
			}
		}

		private bool ControllerCancelPressed()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(_controllerCancelKey))
			{
				return true;
			}
			try
			{
				return InputManager.UI.GetCancelButtonDown((PlayerFarming)null);
			}
			catch
			{
				return false;
			}
		}

		private unsafe void QueueOrClearHoveredType(bool allowNearestFallback)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			Structure val = PlacementRegion.Instance.GetHoveredStructure();
			if ((Object)(object)val == (Object)null && allowNearestFallback)
			{
				val = GetNearestStructureAtPlacement(PlacementRegion.Instance.PlacementPosition, ClearThisTypeConfig.TargetRadius.Value);
			}
			StructureBrain val2 = (((Object)(object)val != (Object)null) ? val.Brain : null);
			if (val2 == null || val2.Data == null)
			{
				Log.LogInfo((object)"Clear This Type: no hovered structure found.");
				ShowStatus("No matching structure under cursor");
				return;
			}
			TYPES type = val2.Data.Type;
			if (!ClearThisTypeConfig.AllowCriticalStructures.Value && IsCritical(type))
			{
				Log.LogWarning((object)("Blocked Clear This Type for protected structure type " + ((object)(*(TYPES*)(&type))/*cast due to .constrained prefix*/).ToString() + "."));
				ShowStatus("Protected structure type");
			}
			else if (ClearThisTypeConfig.RequireConfirmation.Value && (_pendingType != type || Time.unscaledTime > _pendingUntil))
			{
				SetPendingConfirmation(type);
			}
			else
			{
				ClearMatchingType(type);
			}
		}

		private void SetPendingConfirmation(TYPES type)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			_pendingType = type;
			_pendingUntil = Time.unscaledTime + ClearThisTypeConfig.ConfirmationSeconds.Value;
			_pendingName = StructuresData.LocalizedName(type);
			_pendingCount = GetStructuresOfType(type).Count;
			ShowStatus("Remove all " + _pendingName + "? Press again");
		}

		private unsafe void ClearMatchingType(TYPES type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			List<Structure> structuresOfType = GetStructuresOfType(type);
			int value = ClearThisTypeConfig.MaxClearCount.Value;
			int num = 0;
			int num2 = 0;
			int num3 = structuresOfType.Count - 1;
			while (num3 >= 0 && num < value)
			{
				Structure val = structuresOfType[num3];
				if ((Object)(object)val != (Object)null && val.Brain != null && val.Brain.Data != null)
				{
					TYPES toBuildType = val.Brain.Data.ToBuildType;
					if (RemoveStructureCleanly(val))
					{
						num++;
						num2 += RefundBuildSiteMaterials(type, toBuildType);
					}
				}
				num3--;
			}
			Log.LogInfo((object)("Cleared " + num + " structure(s) of type " + ((object)(*(TYPES*)(&type))/*cast due to .constrained prefix*/).ToString() + "."));
			ShowStatus((num2 > 0) ? ("Cleared " + num + "x " + ((object)(*(TYPES*)(&type))/*cast due to .constrained prefix*/).ToString() + " and refunded " + num2 + " item(s)") : ("Cleared " + num + "x " + ((object)(*(TYPES*)(&type))/*cast due to .constrained prefix*/).ToString()));
			ClearPending();
		}

		private static int RefundBuildSiteMaterials(TYPES type, TYPES toBuildType)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			//IL_001e: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			if (!ClearThisTypeConfig.RefundBuildSiteMaterials.Value || ((int)type != 31 && (int)type != 118))
			{
				return 0;
			}
			List<ItemCost> cost = StructuresData.GetCost(((int)toBuildType != 0) ? toBuildType : type);
			if (cost == null)
			{
				return 0;
			}
			int num = 0;
			for (int i = 0; i < cost.Count; i++)
			{
				ItemCost val = cost[i];
				if (val.CostValue > 0)
				{
					Inventory.AddItem(val.CostItem, val.CostValue, true);
					num += val.CostValue;
				}
			}
			return num;
		}

		private void LateUpdate()
		{
			UpdateVanillaPrompt();
		}

		private void OnGUI()
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			if (ClearThisTypeConfig.ShowConfirmationOverlay.Value && ClearThisTypeConfig.Enabled.Value && HasPendingConfirmation() && IsActiveBuildPlacement())
			{
				EnsureStyles();
				float num = Mathf.Min(540f, (float)Screen.width - 48f);
				float num2 = 168f;
				Rect val = default(Rect);
				((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, Mathf.Max(56f, (float)Screen.height * 0.18f), num, num2);
				GUI.Box(val, GUIContent.none, _boxStyle);
				GUI.Label(new Rect(((Rect)(ref val)).x + 24f, ((Rect)(ref val)).y + 18f, ((Rect)(ref val)).width - 48f, 34f), "Remove all " + _pendingName + "?", _titleStyle);
				string text = "This will remove " + _pendingCount + " matching structure" + ((_pendingCount == 1) ? "" : "s") + " from the cult. Press " + ClearThisTypeConfig.ClearKey.Value + " again or use Confirm. Controller: Accept to confirm, Back to cancel.";
				GUI.Label(new Rect(((Rect)(ref val)).x + 24f, ((Rect)(ref val)).y + 58f, ((Rect)(ref val)).width - 48f, 44f), text, _bodyStyle);
				Rect val2 = new Rect(((Rect)(ref val)).x + ((Rect)(ref val)).width - 248f, ((Rect)(ref val)).y + ((Rect)(ref val)).height - 48f, 104f, 30f);
				Rect val3 = default(Rect);
				((Rect)(ref val3))..ctor(((Rect)(ref val)).x + ((Rect)(ref val)).width - 132f, ((Rect)(ref val)).y + ((Rect)(ref val)).height - 48f, 84f, 30f);
				if (GUI.Button(val2, "Confirm", _confirmStyle))
				{
					ClearMatchingType(_pendingType);
				}
				if (GUI.Button(val3, "Cancel", _cancelStyle))
				{
					ClearPending();
					ShowStatus("Remove all cancelled");
				}
			}
		}

		private void UpdateVanillaPrompt()
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			if (!ClearThisTypeConfig.ShowPrompt.Value || !ClearThisTypeConfig.Enabled.Value || (Object)(object)PlacementRegion.Instance == (Object)null || (Object)(object)PlacementObject.Instance == (Object)null || (Object)(object)PlayerFarming.Instance == (Object)null || (Object)(object)PlayerFarming.Instance.indicator == (Object)null || !IsActiveBuildPlacement())
			{
				return;
			}
			Structure val = PlacementRegion.Instance.GetHoveredStructure();
			if ((Object)(object)val == (Object)null)
			{
				val = GetNearestStructureAtPlacement(PlacementRegion.Instance.PlacementPosition, ClearThisTypeConfig.TargetRadius.Value);
			}
			if (!((Object)(object)val == (Object)null) || !(Time.unscaledTime >= _statusUntil))
			{
				string text = (((int)_pendingType != 0 && Time.unscaledTime <= _pendingUntil) ? "Confirm Remove All" : "Remove All");
				Indicator indicator = PlayerFarming.Instance.indicator;
				indicator.HasThirdInteraction = true;
				indicator.ThirdInteractable = true;
				if (ClearThisTypeConfig.UseVanillaPromptSlot.Value)
				{
					indicator.thirdControlPrompt.Category = 0;
					indicator.thirdControlPrompt.Action = 67;
				}
				string text2 = (((Object)(object)indicator.Thirdtext != (Object)null) ? ((TMP_Text)indicator.Thirdtext).text : string.Empty);
				string text3 = ((Time.unscaledTime < _statusUntil && !string.IsNullOrEmpty(_statusText)) ? _statusText : text);
				((TMP_Text)indicator.Thirdtext).text = (ShouldReplacePrompt(text2) ? text3 : text2);
				indicator.Reset();
			}
		}

		private void ClearVanillaPrompt()
		{
			if ((Object)(object)PlayerFarming.Instance != (Object)null && (Object)(object)PlayerFarming.Instance.indicator != (Object)null && (Object)(object)PlayerFarming.Instance.indicator.Fourthtext != (Object)null)
			{
				((TMP_Text)PlayerFarming.Instance.indicator.Fourthtext).text = "";
				PlayerFarming.Instance.indicator.HasFourthInteraction = false;
			}
		}

		private void ShowStatus(string text)
		{
			_statusText = text;
			_statusUntil = Time.unscaledTime + 2f;
		}

		private bool HasPendingConfirmation()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if ((int)_pendingType != 0)
			{
				return Time.unscaledTime <= _pendingUntil;
			}
			return false;
		}

		private void ClearPending()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			_pendingType = (TYPES)0;
			_pendingUntil = 0f;
			_pendingName = "";
			_pendingCount = 0;
		}

		private void EnsureStyles()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			//IL_00ae: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Expected O, but got Unknown
			//IL_0108: 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_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Expected O, but got Unknown
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Expected O, but got Unknown
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Expected O, but got Unknown
			if (_boxStyle == null)
			{
				_boxBackground = MakeTexture(new Color(0.02f, 0.015f, 0.012f, 0.92f));
				_confirmBackground = MakeTexture(new Color(0.66f, 0.08f, 0.06f, 0.94f));
				_cancelBackground = MakeTexture(new Color(0.16f, 0.14f, 0.12f, 0.94f));
				GUIStyle val = new GUIStyle(GUI.skin.box);
				val.normal.background = _boxBackground;
				val.padding = new RectOffset(18, 18, 18, 18);
				_boxStyle = val;
				GUIStyle val2 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 24,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)3
				};
				val2.normal.textColor = new Color(1f, 0.91f, 0.34f, 1f);
				_titleStyle = val2;
				GUIStyle val3 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 16,
					wordWrap = true,
					alignment = (TextAnchor)0
				};
				val3.normal.textColor = Color.white;
				_bodyStyle = val3;
				GUIStyle val4 = new GUIStyle(GUI.skin.button)
				{
					fontSize = 16,
					fontStyle = (FontStyle)1
				};
				val4.normal.background = _confirmBackground;
				val4.normal.textColor = Color.white;
				val4.hover.background = _confirmBackground;
				val4.hover.textColor = Color.white;
				val4.active.background = _confirmBackground;
				val4.active.textColor = Color.white;
				_confirmStyle = val4;
				GUIStyle val5 = new GUIStyle(GUI.skin.button)
				{
					fontSize = 16,
					fontStyle = (FontStyle)1
				};
				val5.normal.background = _cancelBackground;
				val5.normal.textColor = Color.white;
				val5.hover.background = _cancelBackground;
				val5.hover.textColor = Color.white;
				val5.active.background = _cancelBackground;
				val5.active.textColor = Color.white;
				_cancelStyle = val5;
			}
		}

		private static Texture2D MakeTexture(Color color)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1);
			val.SetPixel(0, 0, color);
			val.Apply();
			return val;
		}

		private static void DestroyTexture(ref Texture2D texture)
		{
			if (!((Object)(object)texture == (Object)null))
			{
				Object.Destroy((Object)(object)texture);
				texture = null;
			}
		}

		private static Structure GetNearestStructureAtPlacement(Vector3 position, float radius)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			Structure result = null;
			float num = radius;
			foreach (Structure structure in Structure.Structures)
			{
				if (!((Object)(object)structure == (Object)null) && structure.Brain != null && structure.Brain.Data != null)
				{
					float num2 = Vector3.Distance(position, ((Component)structure).transform.position);
					if (num2 <= num)
					{
						result = structure;
						num = num2;
					}
				}
			}
			return result;
		}

		private static List<Structure> GetStructuresOfType(TYPES type)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			List<Structure> list = new List<Structure>();
			Structure[] array = Structure.Structures.ToArray();
			foreach (Structure val in array)
			{
				if ((Object)(object)val != (Object)null && val.Brain != null && val.Brain.Data != null && val.Brain.Data.Type == type)
				{
					list.Add(val);
				}
			}
			return list;
		}

		private static bool RemoveStructureCleanly(Structure structure)
		{
			if ((Object)(object)structure == (Object)null || structure.Brain == null || structure.Brain.Data == null)
			{
				return false;
			}
			try
			{
				if ((Object)(object)PlacementRegion.Instance != (Object)null)
				{
					PlacementRegion.Instance.DestroyBuilding(structure);
				}
				else
				{
					structure.RemoveStructure();
					Object.Destroy((Object)(object)((Component)structure).gameObject);
				}
				return true;
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Clean removal failed for " + ((object)Unsafe.As<TYPES, TYPES>(ref structure.Type)/*cast due to .constrained prefix*/).ToString() + ": " + ex.Message));
				return false;
			}
		}

		private unsafe static bool IsCritical(TYPES type)
		{
			string text = ((object)(*(TYPES*)(&type))/*cast due to .constrained prefix*/).ToString();
			if (!text.Contains("TEMPLE") && !text.Contains("SHRINE") && !text.Contains("ALTAR"))
			{
				return text.Contains("BUILDER");
			}
			return true;
		}

		private static bool IsActiveBuildPlacement()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Invalid comparison between Unknown and I4
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Invalid comparison between Unknown and I4
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Invalid comparison between Unknown and I4
			if ((Object)(object)PlacementObject.Instance == (Object)null || (Object)(object)PlacementRegion.Instance == (Object)null || (int)PlacementRegion.Instance.CurrentMode == 0)
			{
				return false;
			}
			Mode currentMode = PlacementRegion.Instance.CurrentMode;
			if ((int)currentMode != 1 && (int)currentMode != 5)
			{
				return (int)currentMode == 3;
			}
			return true;
		}

		private static bool ShouldReplacePrompt(string existing)
		{
			if (!string.IsNullOrEmpty(existing) && !existing.Contains("Clear this type") && !existing.Contains("Remove All") && !existing.Contains("Remove all ") && !existing.StartsWith("Cleared ") && !(existing == "Protected structure type") && !(existing == "No matching structure under cursor"))
			{
				return existing == "Remove all cancelled";
			}
			return true;
		}

		private static KeyCode ParseKey(string raw, KeyCode fallback)
		{
			//IL_0011: 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_001a: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return (KeyCode)Enum.Parse(typeof(KeyCode), raw, ignoreCase: true);
			}
			catch
			{
				return fallback;
			}
		}
	}
	internal static class ClearThisTypeConfig
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<string> ClearKey;

		internal static ConfigEntry<string> ControllerConfirmKey;

		internal static ConfigEntry<string> ControllerCancelKey;

		internal static ConfigEntry<int> MaxClearCount;

		internal static ConfigEntry<bool> AllowCriticalStructures;

		internal static ConfigEntry<float> TargetRadius;

		internal static ConfigEntry<bool> ShowPrompt;

		internal static ConfigEntry<bool> EnableVanillaClearButton;

		internal static ConfigEntry<bool> UseVanillaPromptSlot;

		internal static ConfigEntry<bool> ShowConfirmationOverlay;

		internal static ConfigEntry<bool> RequireConfirmation;

		internal static ConfigEntry<float> ConfirmationSeconds;

		internal static ConfigEntry<bool> RefundBuildSiteMaterials;

		internal static void Bind(ConfigFile config)
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Expected O, but got Unknown
			Enabled = config.Bind<bool>("General", "Enabled", true, "Enable Clear This Type.");
			ClearKey = config.Bind<string>("Controls", "ClearKey", "F8", "KeyCode used to clear all structures matching the hovered structure type.");
			ControllerConfirmKey = config.Bind<string>("Controls", "ControllerConfirmKey", "JoystickButton0", "Fallback controller KeyCode used to confirm the custom Remove All prompt. JoystickButton0 is normally A/Cross.");
			ControllerCancelKey = config.Bind<string>("Controls", "ControllerCancelKey", "JoystickButton1", "Fallback controller KeyCode used to cancel the custom Remove All prompt. JoystickButton1 is normally B/Circle.");
			EnableVanillaClearButton = config.Bind<bool>("Controls", "EnableVanillaClearButton", true, "Also trigger Clear This Type from the vanilla third interaction button while actively placing/editing.");
			MaxClearCount = config.Bind<int>("Safety", "MaxClearCount", 250, new ConfigDescription("Maximum structures removed by one clear action.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000), Array.Empty<object>()));
			AllowCriticalStructures = config.Bind<bool>("Safety", "AllowCriticalStructures", false, "Allow clearing temple/shrine/altar/builder style critical structures.");
			TargetRadius = config.Bind<float>("Targeting", "TargetRadius", 1.25f, new ConfigDescription("Fallback radius around the build cursor when vanilla hover targeting returns nothing.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 5f), Array.Empty<object>()));
			ShowPrompt = config.Bind<bool>("UI", "ShowPrompt", true, "Show a small build-mode prompt for Clear This Type.");
			UseVanillaPromptSlot = config.Bind<bool>("UI", "UseVanillaPromptSlot", true, "Use the vanilla third interaction prompt slot/glyph for Clear This Type.");
			ShowConfirmationOverlay = config.Bind<bool>("UI", "ShowConfirmationOverlay", true, "Show a centered confirmation prompt before removing every matching structure.");
			RequireConfirmation = config.Bind<bool>("Safety", "RequireConfirmation", true, "Require pressing Clear Type twice before removing every matching structure.");
			ConfirmationSeconds = config.Bind<float>("Safety", "ConfirmationSeconds", 3f, new ConfigDescription("Seconds the remove-all confirmation remains active.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
			RefundBuildSiteMaterials = config.Bind<bool>("Safety", "RefundBuildSiteMaterials", true, "Refund the full normal cost directly to inventory when Remove All clears unfinished build sites.");
		}
	}
}

plugins/BetterBuilderTools/DragPlaceStructures.dll

Decompiled 2 weeks ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using src.UINavigator;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Drag Place Structures")]
[assembly: AssemblyProduct("Drag Place Structures")]
[assembly: ComVisible(false)]
[assembly: Guid("abefcbd5-7fec-41fa-8ba5-b14640519f34")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyVersion("0.1.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DragPlaceStructures
{
	[BepInPlugin("com.cotl.betterbuildertools.dragplacestructures", "Drag Place Structures", "0.1.4")]
	public sealed class DragPlaceStructuresPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.cotl.betterbuildertools.dragplacestructures";

		public const string PluginName = "Drag Place Structures";

		public const string PluginVersion = "0.1.4";

		private Harmony _harmony;

		private KeyCode _modifierKey;

		private KeyCode _repeatKey;

		private float _lastPlaceTime;

		private Vector2Int _lastPlaceGrid = new Vector2Int(9999, 9999);

		private TYPES _lastStructureType;

		private Mode _lastMode;

		private int _lastCustomBuildFrame = -1;

		private bool _invokingBuild;

		private static readonly MethodInfo BuildMethod = AccessTools.Method(typeof(PlacementRegion), "Build", (Type[])null, (Type[])null);

		internal static ManualLogSource Log { get; private set; }

		internal static DragPlaceStructuresPlugin Instance { get; private set; }

		private void Awake()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			DragPlaceStructuresConfig.Bind(((BaseUnityPlugin)this).Config);
			_modifierKey = ParseKey(DragPlaceStructuresConfig.ModifierKey.Value, (KeyCode)304);
			_repeatKey = ParseKey(DragPlaceStructuresConfig.RepeatKey.Value, (KeyCode)323);
			_harmony = new Harmony("com.cotl.betterbuildertools.dragplacestructures");
			_harmony.PatchAll(typeof(DragPlaceStructuresPlugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Drag Place Structures 0.1.4 loaded.");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			Instance = null;
		}

		private void Update()
		{
			TryDragPlace(PlacementRegion.Instance);
		}

		internal void TryDragPlace(PlacementRegion region)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Invalid comparison between Unknown and I4
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Invalid comparison between Unknown and I4
			//IL_0069: 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)
			//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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: 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_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			if (!DragPlaceStructuresConfig.Enabled.Value || (Object)(object)region == (Object)null || (Object)(object)PlacementObject.Instance == (Object)null)
			{
				ResetPlacementSession();
				return;
			}
			if ((int)region.CurrentMode != 5 && (int)region.CurrentMode != 1)
			{
				ResetPlacementSession();
				return;
			}
			if (region.StructureType != _lastStructureType || region.CurrentMode != _lastMode)
			{
				_lastPlaceGrid = new Vector2Int(9999, 9999);
				_lastPlaceTime = -1f;
				_lastStructureType = region.StructureType;
				_lastMode = region.CurrentMode;
			}
			if ((DragPlaceStructuresConfig.RequireModifier.Value && !Input.GetKey(_modifierKey)) || !IsRepeatHeld() || Time.unscaledTime - _lastPlaceTime < DragPlaceStructuresConfig.PlaceInterval.Value)
			{
				return;
			}
			TYPES structureType = region.StructureType;
			if (!DragPlaceStructuresConfig.AllowPathsToo.Value && StructureBrain.IsPath(structureType))
			{
				return;
			}
			TileGridTile gridTile = GetGridTile(region);
			if (gridTile != null && !(Vector2Int.Distance(gridTile.Position, _lastPlaceGrid) < DragPlaceStructuresConfig.MinDistance.Value))
			{
				Vector2Int bounds = (((Object)(object)PlacementObject.Instance != (Object)null) ? PlacementObject.Instance.Bounds : Vector2Int.one);
				if (CanPlaceBounds(region, gridTile.Position, bounds) && InvokeVanillaBuild(region, structureType, gridTile, bounds))
				{
					_lastPlaceGrid = gridTile.Position;
					_lastPlaceTime = Time.unscaledTime;
				}
			}
		}

		private void ResetPlacementSession()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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)
			_lastPlaceGrid = new Vector2Int(9999, 9999);
			_lastPlaceTime = -1f;
			_lastStructureType = (TYPES)0;
			_lastMode = (Mode)0;
			_lastCustomBuildFrame = -1;
		}

		private bool IsRepeatHeld()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if ((int)_repeatKey == 323 && Input.GetMouseButton(0))
			{
				return true;
			}
			if (Input.GetKey(_repeatKey))
			{
				return true;
			}
			try
			{
				return InputManager.Gameplay.GetPlaceMoveUpgradeButtonHeld(MonoSingleton<UINavigatorNew>.Instance.AllowInputOnlyFromPlayer);
			}
			catch
			{
				return false;
			}
		}

		private static TileGridTile GetGridTile(PlacementRegion region)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return region.GetClosestTileGridTileAtWorldPosition(region.PlacementPosition);
			}
			catch
			{
				return null;
			}
		}

		private static bool CanPlaceBounds(PlacementRegion region, Vector2Int origin, Vector2Int bounds)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < ((Vector2Int)(ref bounds)).x; i++)
			{
				for (int j = 0; j < ((Vector2Int)(ref bounds)).y; j++)
				{
					TileGridTile tileGridTile = region.GetTileGridTile(origin + new Vector2Int(i, j));
					if (tileGridTile == null || !tileGridTile.CanPlaceStructure)
					{
						return false;
					}
				}
			}
			return true;
		}

		private bool InvokeVanillaBuild(PlacementRegion region, TYPES type, TileGridTile tile, Vector2Int bounds)
		{
			//IL_0033: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_invokingBuild = true;
				if (BuildMethod == null)
				{
					region.PlaceStructureAtWorldPosition(type, tile.WorldPosition, bounds);
				}
				else
				{
					BuildMethod.Invoke(region, new object[6] { type, tile.WorldPosition, tile.Position, bounds, false, false });
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Drag placement build failed: " + ex.GetBaseException().Message));
				RepairFailedTile(tile);
				return false;
			}
			finally
			{
				_invokingBuild = false;
			}
			_lastCustomBuildFrame = Time.frameCount;
			if (tile == null || tile.ObjectID < 0 || (int)tile.ObjectOnTile == 0)
			{
				RepairFailedTile(tile);
				Log.LogWarning((object)"Drag placement did not commit a structure; restored the touched grid tile.");
				return false;
			}
			return true;
		}

		private static void RepairFailedTile(TileGridTile tile)
		{
			if (tile != null && tile.ObjectID < 0)
			{
				tile.Occupied = false;
				tile.Obstructed = false;
				tile.ReservedForWaste = false;
				tile.IsUpgrade = false;
				tile.Collapsed = false;
			}
		}

		internal bool ShouldSuppressNativeBuild()
		{
			if (!_invokingBuild)
			{
				return _lastCustomBuildFrame == Time.frameCount;
			}
			return false;
		}

		private static KeyCode ParseKey(string raw, KeyCode fallback)
		{
			//IL_0011: 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_001a: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return (KeyCode)Enum.Parse(typeof(KeyCode), raw, ignoreCase: true);
			}
			catch
			{
				return fallback;
			}
		}
	}
	[HarmonyPatch(typeof(PlacementRegion), "Build")]
	internal static class PlacementRegionBuildPatch
	{
		private static bool Prefix()
		{
			if (!((Object)(object)DragPlaceStructuresPlugin.Instance == (Object)null))
			{
				return !DragPlaceStructuresPlugin.Instance.ShouldSuppressNativeBuild();
			}
			return true;
		}
	}
	internal static class DragPlaceStructuresConfig
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> RequireModifier;

		internal static ConfigEntry<string> ModifierKey;

		internal static ConfigEntry<string> RepeatKey;

		internal static ConfigEntry<float> PlaceInterval;

		internal static ConfigEntry<float> MinDistance;

		internal static ConfigEntry<bool> AllowPathsToo;

		internal static void Bind(ConfigFile config)
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Expected O, but got Unknown
			Enabled = config.Bind<bool>("General", "Enabled", true, "Enable Drag Place Structures.");
			RequireModifier = config.Bind<bool>("Controls", "RequireModifier", false, "Require a modifier while dragging to place repeated structures.");
			ModifierKey = config.Bind<string>("Controls", "ModifierKey", "LeftShift", "KeyCode held while dragging to place repeated structures.");
			RepeatKey = config.Bind<string>("Controls", "RepeatKey", "Mouse0", "KeyCode held to place repeated structures. For controller confirm, try JoystickButton0.");
			PlaceInterval = config.Bind<float>("Behavior", "PlaceInterval", 0.16f, new ConfigDescription("Minimum seconds between drag placements. Matches Path Brush Plus by default.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>()));
			MinDistance = config.Bind<float>("Behavior", "MinDistance", 0.75f, new ConfigDescription("Minimum world distance from the last drag placement.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
			AllowPathsToo = config.Bind<bool>("Behavior", "AllowPathsToo", false, "Also run for path types. Usually Path Brush Plus should handle paths instead.");
		}
	}
}

plugins/BetterBuilderTools/PathBrushPlus.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using MMTools;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using src.UINavigator;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Path Brush Plus")]
[assembly: AssemblyProduct("Path Brush Plus")]
[assembly: ComVisible(false)]
[assembly: Guid("4e4da601-492e-4c50-bf01-530cf2e1ff4d")]
[assembly: AssemblyFileVersion("0.1.6.0")]
[assembly: AssemblyVersion("0.1.6.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PathBrushPlus
{
	[BepInPlugin("com.cotl.betterbuildertools.pathbrushplus", "Path Brush Plus", "0.1.6")]
	public sealed class PathBrushPlusPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.cotl.betterbuildertools.pathbrushplus";

		public const string PluginName = "Path Brush Plus";

		public const string PluginVersion = "0.1.6";

		private Harmony _harmony;

		private float _lastBrushTime;

		private KeyCode _cycleModeKey;

		private KeyCode _controllerCycleModeKey;

		private BrushMode _currentMode;

		private string _statusText;

		private float _statusUntil;

		private readonly HashSet<Vector2Int> _paintedThisHold = new HashSet<Vector2Int>();

		private readonly List<GameObject> _previewObjects = new List<GameObject>();

		private GameObject _promptRowObject;

		private GameObject _promptCellObject;

		private MMControlPrompt _promptControlPrompt;

		private TMP_Text _promptText;

		private bool? _promptWasController;

		private static readonly MethodInfo BuildMethod = AccessTools.Method(typeof(PlacementRegion), "Build", (Type[])null, (Type[])null);

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			PathBrushPlusConfig.Bind(((BaseUnityPlugin)this).Config);
			_currentMode = ParseMode(PathBrushPlusConfig.DefaultMode.Value, BrushMode.ThreeByThree);
			_cycleModeKey = ParseKey(PathBrushPlusConfig.CycleModeKey.Value, (KeyCode)118);
			_controllerCycleModeKey = ParseKey(PathBrushPlusConfig.ControllerCycleModeKey.Value, (KeyCode)338);
			_harmony = new Harmony("com.cotl.betterbuildertools.pathbrushplus");
			_harmony.PatchAll(typeof(PathBrushPlusPlugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Path Brush Plus 0.1.6 loaded.");
		}

		private void OnDestroy()
		{
			ClearPreview();
			DestroyPromptUi();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
		}

		private void Update()
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Invalid comparison between Unknown and I4
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Invalid comparison between Unknown and I4
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			if (!PathBrushPlusConfig.Enabled.Value || (Object)(object)PlacementRegion.Instance == (Object)null || (Object)(object)PlacementObject.Instance == (Object)null)
			{
				_paintedThisHold.Clear();
				ClearPreview();
				return;
			}
			PlacementRegion instance = PlacementRegion.Instance;
			if (IsPathPlacement(instance))
			{
				HandleModeToggle();
			}
			if ((int)instance.CurrentMode != 5 && (int)instance.CurrentMode != 1)
			{
				_paintedThisHold.Clear();
				return;
			}
			TYPES structureType = instance.StructureType;
			if (PathBrushPlusConfig.PathsOnly.Value && !StructureBrain.IsPath(structureType))
			{
				_paintedThisHold.Clear();
				return;
			}
			if (_currentMode == BrushMode.Vanilla)
			{
				_paintedThisHold.Clear();
				return;
			}
			bool flag = IsPlaceHeld();
			bool flag2 = IsRemoveHeld();
			if (!flag && !flag2)
			{
				_paintedThisHold.Clear();
			}
			else if (!(Time.unscaledTime - _lastBrushTime < PathBrushPlusConfig.BrushInterval.Value))
			{
				_lastBrushTime = Time.unscaledTime;
				ApplyBrush(instance, structureType, flag, flag2);
			}
		}

		private void LateUpdate()
		{
			UpdatePreview();
			UpdatePrompt();
		}

		private void ApplyBrush(PlacementRegion region, TYPES type, bool placeHeld, bool removeHeld)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			List<Vector2Int> brushOffsets = GetBrushOffsets();
			if (brushOffsets.Count == 0)
			{
				return;
			}
			TileGridTile centerTile = GetCenterTile(region);
			if (centerTile == null)
			{
				return;
			}
			for (int i = 0; i < brushOffsets.Count; i++)
			{
				Vector2Int val = brushOffsets[i];
				if (val == Vector2Int.zero)
				{
					continue;
				}
				TileGridTile tileGridTile = region.GetTileGridTile(centerTile.Position + val);
				if (tileGridTile != null)
				{
					if (removeHeld)
					{
						PathTileManager.Instance.DeleteTile(tileGridTile.WorldPosition);
						_paintedThisHold.Remove(tileGridTile.Position);
					}
					else if (placeHeld && !_paintedThisHold.Contains(tileGridTile.Position))
					{
						BuildPath(region, type, tileGridTile);
						_paintedThisHold.Add(tileGridTile.Position);
					}
				}
			}
		}

		private static TileGridTile GetCenterTile(PlacementRegion region)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return region.GetClosestTileGridTileAtWorldPosition(region.PlacementPosition);
			}
			catch
			{
				return null;
			}
		}

		private static void BuildPath(PlacementRegion region, TYPES type, TileGridTile tile)
		{
			//IL_006a: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (BuildMethod != null)
			{
				BuildMethod.Invoke(region, new object[6]
				{
					type,
					tile.WorldPosition,
					tile.Position,
					Vector2Int.one,
					true,
					false
				});
			}
			else
			{
				PathTileManager.Instance.DeleteTile(tile.WorldPosition);
				PathTileManager.Instance.DisplayTile(type, tile.WorldPosition);
				PathTileManager.Instance.SetTile(type, tile.WorldPosition);
			}
		}

		private static bool IsPlaceHeld()
		{
			try
			{
				return InputManager.Gameplay.GetPlaceMoveUpgradeButtonHeld(MonoSingleton<UINavigatorNew>.Instance.AllowInputOnlyFromPlayer);
			}
			catch
			{
				return Input.GetMouseButton(0);
			}
		}

		private static bool IsRemoveHeld()
		{
			try
			{
				return InputManager.Gameplay.GetRemoveFlipButtonHeld(MonoSingleton<UINavigatorNew>.Instance.AllowInputOnlyFromPlayer);
			}
			catch
			{
				return Input.GetMouseButton(1);
			}
		}

		private void UpdatePreview()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			if (!PathBrushPlusConfig.ShowBrushPreview.Value || !PathBrushPlusConfig.Enabled.Value || (Object)(object)PlacementRegion.Instance == (Object)null || (Object)(object)PlacementObject.Instance == (Object)null || _currentMode == BrushMode.Vanilla)
			{
				ClearPreview();
				return;
			}
			PlacementRegion instance = PlacementRegion.Instance;
			if (PathBrushPlusConfig.PathsOnly.Value && !StructureBrain.IsPath(instance.StructureType))
			{
				ClearPreview();
				return;
			}
			TileGridTile centerTile = GetCenterTile(instance);
			List<Vector2Int> brushOffsets = GetBrushOffsets(includeCenter: true);
			if (centerTile == null || brushOffsets.Count == 0 || (Object)(object)instance.PlacementSquare == (Object)null)
			{
				ClearPreview();
				return;
			}
			EnsurePreviewCount(instance, brushOffsets.Count);
			int num = 0;
			for (int i = 0; i < brushOffsets.Count; i++)
			{
				Vector2Int val = brushOffsets[i];
				TileGridTile tileGridTile = instance.GetTileGridTile(centerTile.Position + val);
				GameObject val2 = _previewObjects[num++];
				if (tileGridTile == null)
				{
					val2.SetActive(false);
					continue;
				}
				val2.SetActive(true);
				val2.transform.SetParent(((Component)instance).transform, false);
				val2.transform.localPosition = new Vector3((float)((Vector2Int)(ref tileGridTile.Position)).x, (float)((Vector2Int)(ref tileGridTile.Position)).y, -0.05f);
				ApplyPreviewColor(val2, val == Vector2Int.zero);
			}
			for (int j = num; j < _previewObjects.Count; j++)
			{
				_previewObjects[j].SetActive(false);
			}
		}

		private void EnsurePreviewCount(PlacementRegion region, int needed)
		{
			while (_previewObjects.Count < needed)
			{
				GameObject val = Object.Instantiate<GameObject>(region.PlacementSquare, ((Component)region).transform);
				((Object)val).name = "PathBrushPlusPreview";
				Collider2D[] componentsInChildren = val.GetComponentsInChildren<Collider2D>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					((Behaviour)componentsInChildren[i]).enabled = false;
				}
				_previewObjects.Add(val);
			}
		}

		private static void ApplyPreviewColor(GameObject preview, bool center)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			SpriteRenderer[] componentsInChildren = preview.GetComponentsInChildren<SpriteRenderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].color = (center ? new Color(0.1f, 1f, 0.1f, 0.9f) : new Color(0.1f, 0.85f, 1f, 0.55f));
			}
		}

		private void ClearPreview()
		{
			for (int i = 0; i < _previewObjects.Count; i++)
			{
				if ((Object)(object)_previewObjects[i] != (Object)null)
				{
					Object.Destroy((Object)(object)_previewObjects[i]);
				}
			}
			_previewObjects.Clear();
		}

		private void HandleModeToggle()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(_cycleModeKey) || (PathBrushPlusConfig.EnableControllerModeCycle.Value && Input.GetKeyDown(_controllerCycleModeKey)))
			{
				_currentMode = NextMode(_currentMode);
				_paintedThisHold.Clear();
				ClearPreview();
				ShowStatus("Path brush: " + ModeLabel(_currentMode));
			}
		}

		private void UpdatePrompt()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			if (!PathBrushPlusConfig.ShowModePrompt.Value || !PathBrushPlusConfig.Enabled.Value || (Object)(object)PlacementRegion.Instance == (Object)null || (Object)(object)PlacementObject.Instance == (Object)null || (Object)(object)PlayerFarming.Instance == (Object)null || (Object)(object)PlayerFarming.Instance.indicator == (Object)null)
			{
				HidePrompt();
				return;
			}
			PlacementRegion instance = PlacementRegion.Instance;
			if (!IsPathPlacement(instance) || (PathBrushPlusConfig.PathsOnly.Value && !StructureBrain.IsPath(instance.StructureType)))
			{
				HidePrompt();
			}
			else if (EnsurePrompt(PlayerFarming.Instance.indicator))
			{
				string text = ((Time.unscaledTime < _statusUntil && !string.IsNullOrEmpty(_statusText)) ? _statusText : ("Brush: " + ModeLabel(_currentMode)));
				bool flag = IsControllerInput();
				_promptControlPrompt.playerFarming = PlayerFarming.Instance;
				_promptControlPrompt.PrioritizeMouse = false;
				_promptText.text = text;
				_promptCellObject.SetActive(true);
				SizePromptRow(_promptRowObject);
				_promptRowObject.SetActive(true);
				if (_promptWasController != flag)
				{
					_promptWasController = flag;
					RefreshPromptGlyph(flag);
				}
			}
		}

		private bool EnsurePrompt(Indicator indicator)
		{
			if ((Object)(object)_promptCellObject != (Object)null && (Object)(object)_promptControlPrompt != (Object)null && (Object)(object)_promptText != (Object)null)
			{
				return true;
			}
			if ((Object)(object)indicator == (Object)null || (Object)(object)indicator.FourthControlPrompt == (Object)null || (Object)(object)((Transform)indicator.FourthControlPrompt).parent == (Object)null || (Object)(object)indicator.Fourthtext == (Object)null)
			{
				return false;
			}
			EnsurePromptRow(indicator);
			if ((Object)(object)_promptRowObject == (Object)null)
			{
				return false;
			}
			CreatePromptCell(indicator);
			if ((Object)(object)_promptControlPrompt == (Object)null || (Object)(object)_promptText == (Object)null)
			{
				DestroyPromptUi();
				return false;
			}
			_promptWasController = null;
			return true;
		}

		private void EnsurePromptRow(Indicator indicator)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			Transform promptParent = GetPromptParent(indicator);
			if (!((Object)(object)promptParent == (Object)null))
			{
				Transform val = promptParent.Find("RemoteBuildCancel_BuilderToolsPromptRow");
				if ((Object)(object)val != (Object)null)
				{
					ConfigurePromptRow(((Component)val).gameObject);
					AddVanillaPromptBackground(((Component)val).gameObject, indicator);
					_promptRowObject = ((Component)val).gameObject;
					_promptRowObject.SetActive(true);
				}
				else
				{
					GameObject val2 = new GameObject("RemoteBuildCancel_BuilderToolsPromptRow");
					((Transform)val2.AddComponent<RectTransform>()).SetParent(promptParent, false);
					ConfigurePromptRow(val2);
					AddVanillaPromptBackground(val2, indicator);
					val2.transform.SetAsLastSibling();
					_promptRowObject = val2;
				}
			}
		}

		private static void ConfigurePromptRow(GameObject row)
		{
			//IL_001b: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Expected O, but got Unknown
			RectTransform obj = row.GetComponent<RectTransform>() ?? row.AddComponent<RectTransform>();
			obj.anchorMin = new Vector2(0.5f, 0f);
			obj.anchorMax = new Vector2(0.5f, 0f);
			obj.pivot = new Vector2(0f, 0f);
			obj.anchoredPosition = new Vector2(240f, 112f);
			obj.sizeDelta = new Vector2(0f, 52f);
			LayoutElement obj2 = row.GetComponent<LayoutElement>() ?? row.AddComponent<LayoutElement>();
			obj2.minWidth = 0f;
			obj2.preferredWidth = 0f;
			obj2.flexibleWidth = 0f;
			obj2.minHeight = 52f;
			obj2.preferredHeight = 52f;
			obj2.flexibleHeight = 0f;
			ContentSizeFitter obj3 = row.GetComponent<ContentSizeFitter>() ?? row.AddComponent<ContentSizeFitter>();
			obj3.horizontalFit = (FitMode)2;
			obj3.verticalFit = (FitMode)0;
			((Behaviour)obj3).enabled = false;
			HorizontalLayoutGroup obj4 = row.GetComponent<HorizontalLayoutGroup>() ?? row.AddComponent<HorizontalLayoutGroup>();
			((LayoutGroup)obj4).padding = new RectOffset(18, 18, 5, 5);
			((HorizontalOrVerticalLayoutGroup)obj4).spacing = 18f;
			((LayoutGroup)obj4).childAlignment = (TextAnchor)4;
			((HorizontalOrVerticalLayoutGroup)obj4).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj4).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj4).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj4).childForceExpandHeight = true;
		}

		private static void SizePromptRow(GameObject row)
		{
			//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)
			if ((Object)(object)row == (Object)null)
			{
				return;
			}
			RectTransform component = row.GetComponent<RectTransform>();
			HorizontalLayoutGroup component2 = row.GetComponent<HorizontalLayoutGroup>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
			{
				return;
			}
			float num = ((LayoutGroup)component2).padding.left + ((LayoutGroup)component2).padding.right;
			int num2 = 0;
			for (int i = 0; i < row.transform.childCount; i++)
			{
				GameObject gameObject = ((Component)row.transform.GetChild(i)).gameObject;
				if (!gameObject.activeSelf || ((Object)gameObject).name.IndexOf("VanillaPromptBackground", StringComparison.Ordinal) >= 0)
				{
					continue;
				}
				LayoutElement component3 = gameObject.GetComponent<LayoutElement>();
				float num3 = (((Object)(object)component3 != (Object)null) ? Mathf.Max(component3.minWidth, component3.preferredWidth) : 0f);
				if (num3 <= 0f)
				{
					RectTransform component4 = gameObject.GetComponent<RectTransform>();
					float num4;
					if (!((Object)(object)component4 != (Object)null))
					{
						num4 = 0f;
					}
					else
					{
						Rect rect = component4.rect;
						num4 = ((Rect)(ref rect)).width;
					}
					num3 = num4;
				}
				if (num3 <= 0f)
				{
					num3 = 40f;
				}
				if (num2 > 0)
				{
					num += ((HorizontalOrVerticalLayoutGroup)component2).spacing;
				}
				num += num3;
				num2++;
			}
			num = Mathf.Max(num, 1f);
			component.SetSizeWithCurrentAnchors((Axis)0, num);
			component.SetSizeWithCurrentAnchors((Axis)1, 52f);
			LayoutElement component5 = row.GetComponent<LayoutElement>();
			if ((Object)(object)component5 != (Object)null)
			{
				component5.minWidth = num;
				component5.preferredWidth = num;
			}
		}

		private static Transform GetPromptParent(Indicator indicator)
		{
			Transform val = (((Object)(object)indicator != (Object)null && (Object)(object)indicator.ControlPromptUI != (Object)null) ? indicator.ControlPromptUI.transform : (((Object)(object)indicator != (Object)null) ? ((Component)indicator).transform : null));
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Canvas val2 = ((Component)val).GetComponent<Canvas>() ?? ((Component)val).GetComponentInParent<Canvas>();
			if (!((Object)(object)val2 != (Object)null))
			{
				if (!((Object)(object)val.parent != (Object)null))
				{
					return val;
				}
				return val.parent;
			}
			return ((Component)val2).transform;
		}

		private static void AddVanillaPromptBackground(GameObject row, Indicator indicator)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			Image val = (((Object)(object)indicator != (Object)null && (Object)(object)indicator.BG != (Object)null) ? (((Component)indicator.BG).GetComponent<Image>() ?? ((Component)indicator.BG).GetComponentInChildren<Image>(true)) : null);
			Image val2 = row.GetComponent<Image>() ?? row.AddComponent<Image>();
			((Behaviour)val2).enabled = true;
			((Graphic)val2).raycastTarget = false;
			val2.sprite = (((Object)(object)val != (Object)null) ? val.sprite : null);
			val2.type = (Type)(((Object)(object)val != (Object)null) ? ((int)val.type) : 0);
			if ((Object)(object)val2.sprite == (Object)null)
			{
				val2.sprite = Sprite.Create(Texture2D.whiteTexture, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f));
				val2.type = (Type)0;
			}
			((Graphic)val2).color = new Color(0f, 0f, 0f, 0.88f);
			((Graphic)val2).canvasRenderer.SetColor(((Graphic)val2).color);
			for (int i = 0; i < row.transform.childCount; i++)
			{
				Transform child = row.transform.GetChild(i);
				if (((Object)child).name.IndexOf("VanillaPromptBackground", StringComparison.Ordinal) >= 0)
				{
					((Component)child).gameObject.SetActive(false);
				}
			}
		}

		private void CreatePromptCell(Indicator indicator)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("PathBrushPlus_ModeCell");
			((Transform)val.AddComponent<RectTransform>()).SetParent(_promptRowObject.transform, false);
			LayoutElement obj = val.AddComponent<LayoutElement>();
			obj.preferredWidth = 150f;
			obj.minWidth = 150f;
			HorizontalLayoutGroup obj2 = val.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj2).spacing = 6f;
			((LayoutGroup)obj2).childAlignment = (TextAnchor)4;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = true;
			GameObject val2 = Object.Instantiate<GameObject>(((Component)indicator.FourthControlPrompt).gameObject, val.transform, false);
			((Object)val2).name = "PathBrushPlus_ModeKey";
			val2.SetActive(true);
			val2.transform.localScale = Vector3.one;
			_promptControlPrompt = val2.GetComponent<MMControlPrompt>() ?? val2.GetComponentInChildren<MMControlPrompt>(true);
			LayoutElement obj3 = val2.GetComponent<LayoutElement>() ?? val2.AddComponent<LayoutElement>();
			obj3.preferredWidth = 50f;
			obj3.minWidth = 42f;
			obj3.preferredHeight = 40f;
			TMP_Text val3 = (TMP_Text)(object)Object.Instantiate<TextMeshProUGUI>(indicator.Fourthtext, val.transform, false);
			((Object)((Component)val3).gameObject).name = "PathBrushPlus_ModeLabel";
			((Component)val3).gameObject.SetActive(true);
			val3.transform.localScale = Vector3.one;
			val3.alignment = (TextAlignmentOptions)4097;
			val3.enableAutoSizing = true;
			val3.fontSizeMin = 12f;
			val3.fontSizeMax = 22f;
			LayoutElement obj4 = ((Component)val3).GetComponent<LayoutElement>() ?? ((Component)val3).gameObject.AddComponent<LayoutElement>();
			obj4.preferredWidth = 90f;
			obj4.minWidth = 90f;
			Behaviour[] components = ((Component)val3).GetComponents<Behaviour>();
			foreach (Behaviour val4 in components)
			{
				if ((Object)(object)val4 != (Object)null && ((object)val4).GetType().FullName == "I2.Loc.Localize")
				{
					val4.enabled = false;
				}
			}
			_promptCellObject = val;
			_promptText = val3;
		}

		private void RefreshPromptGlyph(bool controller)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_promptControlPrompt == (Object)null))
			{
				SetCustomPromptKey(_promptControlPrompt, controller ? ControllerButtonLabel(_controllerCycleModeKey) : PathBrushPlusConfig.CycleModeKey.Value);
			}
		}

		private unsafe static string ControllerButtonLabel(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected I4, but got Unknown
			return (key - 330) switch
			{
				0 => "A", 
				1 => "B", 
				2 => "X", 
				3 => "Y", 
				4 => "LB", 
				5 => "RB", 
				6 => "Back", 
				7 => "Start", 
				8 => "LS", 
				9 => "RS", 
				_ => ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString().Replace("JoystickButton", "Pad "), 
			};
		}

		private static void SetCustomPromptKey(MMControlPrompt prompt, string label)
		{
			prompt.IgnoreControllerChange = true;
			object? obj = AccessTools.Field(typeof(MMControlPrompt), "_text")?.GetValue(prompt);
			TMP_Text val = (TMP_Text)((obj is TMP_Text) ? obj : null);
			object? obj2 = AccessTools.Field(typeof(MMControlPrompt), "_iconText")?.GetValue(prompt);
			TMP_Text val2 = (TMP_Text)((obj2 is TMP_Text) ? obj2 : null);
			object? obj3 = AccessTools.Field(typeof(MMControlPrompt), "_icon")?.GetValue(prompt);
			Image val3 = (Image)((obj3 is Image) ? obj3 : null);
			if ((Object)(object)val != (Object)null)
			{
				val.text = label;
				val.fontSize = 20f;
				val.enableAutoSizing = true;
				val.fontSizeMin = 8f;
				val.fontSizeMax = 20f;
				((Component)val).gameObject.SetActive(true);
			}
			if ((Object)(object)val2 != (Object)null)
			{
				((Component)val2).gameObject.SetActive(false);
			}
			if ((Object)(object)val3 != (Object)null)
			{
				((Component)val3).gameObject.SetActive(true);
			}
		}

		private static bool IsControllerInput()
		{
			try
			{
				return (Object)(object)PlayerFarming.Instance != (Object)null && InputManager.General.InputIsController(PlayerFarming.Instance);
			}
			catch
			{
				return false;
			}
		}

		private void HidePrompt()
		{
			if ((Object)(object)_promptCellObject != (Object)null)
			{
				_promptCellObject.SetActive(false);
			}
			RefreshPromptRowVisibility(_promptRowObject);
		}

		private static void RefreshPromptRowVisibility(GameObject row)
		{
			if ((Object)(object)row == (Object)null)
			{
				return;
			}
			bool active = false;
			for (int i = 0; i < row.transform.childCount; i++)
			{
				GameObject gameObject = ((Component)row.transform.GetChild(i)).gameObject;
				if (gameObject.activeSelf && ((Object)gameObject).name.IndexOf("VanillaPromptBackground", StringComparison.Ordinal) < 0)
				{
					active = true;
					break;
				}
			}
			SizePromptRow(row);
			row.SetActive(active);
		}

		private void DestroyPromptUi()
		{
			if ((Object)(object)_promptCellObject != (Object)null)
			{
				Object.Destroy((Object)(object)_promptCellObject);
			}
			_promptCellObject = null;
			_promptControlPrompt = null;
			_promptText = null;
			_promptWasController = null;
			_promptRowObject = null;
		}

		private static bool IsPathPlacement(PlacementRegion region)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			if ((Object)(object)region != (Object)null)
			{
				if ((int)region.CurrentMode != 5)
				{
					return (int)region.CurrentMode == 1;
				}
				return true;
			}
			return false;
		}

		private List<Vector2Int> GetBrushOffsets(bool includeCenter = false)
		{
			if (_currentMode == BrushMode.Vanilla)
			{
				return new List<Vector2Int>();
			}
			if (_currentMode == BrushMode.Fill)
			{
				return GetSquareOffsets(PathBrushPlusConfig.FillSize.Value, includeCenter);
			}
			int value = PathBrushPlusConfig.BrushRadius.Value;
			if (value <= 0)
			{
				return new List<Vector2Int>();
			}
			return GetSquareOffsets(value * 2 + 1, includeCenter);
		}

		private static List<Vector2Int> GetSquareOffsets(int size, bool includeCenter)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			List<Vector2Int> list = new List<Vector2Int>();
			if (size <= 1)
			{
				return list;
			}
			int num = -(size / 2);
			int num2 = num + size - 1;
			Vector2Int val = default(Vector2Int);
			for (int i = num; i <= num2; i++)
			{
				for (int j = num; j <= num2; j++)
				{
					((Vector2Int)(ref val))..ctor(i, j);
					if (includeCenter || !(val == Vector2Int.zero))
					{
						list.Add(val);
					}
				}
			}
			return list;
		}

		private void ShowStatus(string text)
		{
			_statusText = text;
			_statusUntil = Time.unscaledTime + 1.5f;
		}

		private static BrushMode NextMode(BrushMode mode)
		{
			return mode switch
			{
				BrushMode.Vanilla => BrushMode.ThreeByThree, 
				BrushMode.ThreeByThree => BrushMode.Fill, 
				_ => BrushMode.Vanilla, 
			};
		}

		private static string ModeLabel(BrushMode mode)
		{
			switch (mode)
			{
			case BrushMode.Vanilla:
				return "1x1";
			case BrushMode.Fill:
				return PathBrushPlusConfig.FillSize.Value + "x" + PathBrushPlusConfig.FillSize.Value;
			default:
			{
				int num = PathBrushPlusConfig.BrushRadius.Value * 2 + 1;
				return num + "x" + num;
			}
			}
		}

		private static BrushMode ParseMode(string raw, BrushMode fallback)
		{
			try
			{
				return (BrushMode)Enum.Parse(typeof(BrushMode), raw, ignoreCase: true);
			}
			catch
			{
				return fallback;
			}
		}

		private static KeyCode ParseKey(string raw, KeyCode fallback)
		{
			//IL_0011: 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_001a: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return (KeyCode)Enum.Parse(typeof(KeyCode), raw, ignoreCase: true);
			}
			catch
			{
				return fallback;
			}
		}
	}
	internal enum BrushMode
	{
		Vanilla,
		ThreeByThree,
		Fill
	}
	internal static class PathBrushPlusConfig
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<string> DefaultMode;

		internal static ConfigEntry<string> CycleModeKey;

		internal static ConfigEntry<bool> EnableControllerModeCycle;

		internal static ConfigEntry<string> ControllerCycleModeKey;

		internal static ConfigEntry<int> BrushRadius;

		internal static ConfigEntry<int> FillSize;

		internal static ConfigEntry<bool> PathsOnly;

		internal static ConfigEntry<float> BrushInterval;

		internal static ConfigEntry<bool> ShowBrushPreview;

		internal static ConfigEntry<bool> ShowModePrompt;

		internal static ConfigEntry<bool> UseVanillaPromptSlot;

		internal static void Bind(ConfigFile config)
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Expected O, but got Unknown
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Expected O, but got Unknown
			Enabled = config.Bind<bool>("General", "Enabled", true, "Enable Path Brush Plus.");
			DefaultMode = config.Bind<string>("Brush", "DefaultMode", "ThreeByThree", "Starting brush mode: Vanilla, ThreeByThree, or Fill.");
			CycleModeKey = config.Bind<string>("Controls", "CycleModeKey", "V", "KeyCode used while placing paths to cycle Vanilla, 3x3, and Fill brush modes.");
			EnableControllerModeCycle = config.Bind<bool>("Controls", "EnableControllerModeCycle", true, "Enable the configured controller KeyCode for cycling path brush modes.");
			ControllerCycleModeKey = config.Bind<string>("Controls", "ControllerCycleModeKey", "JoystickButton8", "Controller KeyCode used while placing paths to cycle brush modes.");
			BrushRadius = config.Bind<int>("Brush", "BrushRadius", 1, new ConfigDescription("Extra path radius. 1 makes a 3x3 brush.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 4), Array.Empty<object>()));
			FillSize = config.Bind<int>("Brush", "FillSize", 10, new ConfigDescription("Square brush width/height used by Fill mode.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 20), Array.Empty<object>()));
			PathsOnly = config.Bind<bool>("Brush", "PathsOnly", true, "Only apply the brush to StructureBrain path types.");
			BrushInterval = config.Bind<float>("Brush", "BrushInterval", 0.16f, new ConfigDescription("Minimum seconds between brush applications while holding place/remove.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 0.5f), Array.Empty<object>()));
			ShowBrushPreview = config.Bind<bool>("UI", "ShowBrushPreview", true, "Show a separate preview overlay for the full brush area.");
			ShowModePrompt = config.Bind<bool>("UI", "ShowModePrompt", true, "Show the current path brush mode on the vanilla placement indicator.");
			UseVanillaPromptSlot = config.Bind<bool>("UI", "UseVanillaPromptSlot", false, "Use the deprecated vanilla fourth prompt slot for brush mode. This slot uses vanilla's back/cancel glyph, so leave this off unless you want the old text-only prompt behavior.");
			if (BrushInterval.Value < 0.16f)
			{
				BrushInterval.Value = 0.16f;
			}
		}
	}
}

plugins/BetterBuilderTools/RemoteBuildCancel.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Lamb.UI;
using MMTools;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Remote Build Cancel")]
[assembly: AssemblyProduct("Remote Build Cancel")]
[assembly: ComVisible(false)]
[assembly: Guid("04fd6213-8fb5-4236-8792-8e002100f026")]
[assembly: AssemblyFileVersion("0.1.6.0")]
[assembly: AssemblyVersion("0.1.6.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RemoteBuildCancel
{
	[BepInPlugin("com.cotl.betterbuildertools.remotebuildcancel", "Remote Build Cancel", "0.1.9")]
	public sealed class RemoteBuildCancelPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.cotl.betterbuildertools.remotebuildcancel";

		public const string PluginName = "Remote Build Cancel";

		public const string PluginVersion = "0.1.9";

		private Harmony _harmony;

		private KeyCode _cancelKey;

		private KeyCode _mouseCancelKey;

		private KeyCode _controllerCancelKey;

		private KeyCode _editModeKey;

		private int _lastBuiltId = -1;

		private bool _hasCachedBuildMode;

		private TYPES _cachedBuildType;

		private GameObject _cachedPlacementPrefab;

		private Mode _cachedBuildMode = (Mode)5;

		private bool _hasLastBuildSelection;

		private TYPES _lastBuildType;

		private GameObject _lastBuildPlacementPrefab;

		private Mode _lastBuildMode = (Mode)5;

		private float _preserveCachedModeUntil;

		private Indicator _promptOwner;

		private GameObject _modePromptObject;

		private GameObject _modePromptTextObject;

		private MMControlPrompt _modeControlPrompt;

		private TMP_Text _modePromptText;

		private GameObject _cancelPromptObject;

		private GameObject _cancelPromptTextObject;

		private MMControlPrompt _cancelControlPrompt;

		private TMP_Text _cancelPromptText;

		private GameObject _promptRowObject;

		private GameObject _modePromptCellObject;

		private GameObject _cancelPromptCellObject;

		private bool _promptCreationWarningLogged;

		private bool? _modePromptWasController;

		private bool? _cancelPromptWasController;

		private static readonly MethodInfo ClearPrefabsMethod = AccessTools.Method(typeof(PlacementRegion), "ClearPrefabs", (Type[])null, (Type[])null);

		private static readonly FieldInfo TilesField = AccessTools.Field(typeof(PlacementRegion), "Tiles");

		private static readonly FieldInfo TilesInitiatedField = AccessTools.Field(typeof(PlacementRegion), "tilesInitiated");

		private static readonly FieldInfo IsEditingBuildingsField = AccessTools.Field(typeof(PlacementRegion), "isEditingBuildings");

		private static readonly FieldInfo PreviousEditingPositionField = AccessTools.Field(typeof(PlacementRegion), "previousEditingPosition");

		private static readonly FieldInfo CurrentStructureToMoveField = AccessTools.Field(typeof(PlacementRegion), "CurrentStructureToMove");

		private static readonly FieldInfo CurrentStructureToUpgradeField = AccessTools.Field(typeof(PlacementRegion), "CurrentStructureToUpgrade");

		private static readonly FieldInfo PlacementObjectField = AccessTools.Field(typeof(PlacementRegion), "placementObject");

		private static readonly FieldInfo PlacementUiField = AccessTools.Field(typeof(PlacementRegion), "placementUI");

		internal static ManualLogSource Log { get; private set; }

		internal static RemoteBuildCancelPlugin Instance { get; private set; }

		private void Awake()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			RemoteBuildCancelConfig.Bind(((BaseUnityPlugin)this).Config);
			_cancelKey = ParseKey(RemoteBuildCancelConfig.CancelKey.Value, (KeyCode)290);
			_mouseCancelKey = ParseKey(RemoteBuildCancelConfig.MouseCancelKey.Value, (KeyCode)325);
			_controllerCancelKey = ParseKey(RemoteBuildCancelConfig.ControllerCancelKey.Value, (KeyCode)332);
			_editModeKey = ParseKey(RemoteBuildCancelConfig.EditModeKey.Value, (KeyCode)99);
			_harmony = new Harmony("com.cotl.betterbuildertools.remotebuildcancel");
			_harmony.PatchAll(typeof(RemoteBuildCancelPlugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Remote Build Cancel 0.1.9 loaded.");
		}

		private void OnDestroy()
		{
			DestroyAllPromptUi();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			Instance = null;
		}

		private unsafe void Update()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: 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)
			if (!RemoteBuildCancelConfig.Enabled.Value)
			{
				HideModePrompt();
				HideCancelPrompt();
				return;
			}
			RememberActiveBuildSelection();
			if (!IsActiveBuildPlacement())
			{
				if (((Object)(object)PlacementRegion.Instance == (Object)null || (int)PlacementRegion.Instance.CurrentMode == 0) && Time.unscaledTime >= _preserveCachedModeUntil)
				{
					ClearCachedBuildMode();
				}
				HideModePrompt();
				HideCancelPrompt();
			}
			else if (RemoteBuildCancelConfig.EnableEditModeToggle.Value && EditModePressed())
			{
				ToggleBuildEditMode();
			}
			else
			{
				if (!CancelPressed())
				{
					return;
				}
				Structure val = GetHoveredStructure();
				if ((Object)(object)val == (Object)null && RemoteBuildCancelConfig.FallbackToLastPlaced.Value)
				{
					val = FindStructureById(_lastBuiltId);
				}
				if ((Object)(object)val == (Object)null || val.Brain == null || val.Brain.Data == null)
				{
					Log.LogInfo((object)"Remote cancel: no hovered/latest structure found.");
					return;
				}
				if (RemoteBuildCancelConfig.OnlyCancelBuildSites.Value && !IsBuildSite(val.Brain.Data.Type))
				{
					Log.LogInfo((object)("Remote cancel ignored non-build-site structure " + ((object)Unsafe.As<TYPES, TYPES>(ref val.Brain.Data.Type)/*cast due to .constrained prefix*/).ToString() + "."));
					return;
				}
				if (!RemoteBuildCancelConfig.AllowCriticalStructures.Value && IsCritical(val.Brain.Data.Type))
				{
					Log.LogWarning((object)("Blocked remote cancel for protected structure type " + ((object)Unsafe.As<TYPES, TYPES>(ref val.Brain.Data.Type)/*cast due to .constrained prefix*/).ToString() + "."));
					return;
				}
				TYPES type = val.Brain.Data.Type;
				if (RemoveStructureCleanly(val))
				{
					Log.LogInfo((object)("Remote canceled " + ((object)(*(TYPES*)(&type))/*cast due to .constrained prefix*/).ToString() + "."));
				}
			}
		}

		private void LateUpdate()
		{
			UpdateEditModePrompt();
			UpdateCancelPrompt();
		}

		private bool CancelPressed()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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)
			if (Input.GetKeyDown(_cancelKey) || Input.GetKeyDown(_mouseCancelKey))
			{
				return true;
			}
			if (RemoteBuildCancelConfig.EnableControllerCancel.Value)
			{
				return Input.GetKeyDown(_controllerCancelKey);
			}
			return false;
		}

		private bool EditModePressed()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(_editModeKey) || Input.GetKeyDown((KeyCode)99))
			{
				return true;
			}
			if (!RemoteBuildCancelConfig.UseVanillaEditModeAction.Value)
			{
				return false;
			}
			try
			{
				return InputManager.UI.GetEditBuildingsButtonDown((PlayerFarming)null);
			}
			catch
			{
				return false;
			}
		}

		private void ToggleBuildEditMode()
		{
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			PlacementRegion instance = PlacementRegion.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			Log.LogInfo((object)("Edit toggle request: mode=" + ((object)Unsafe.As<Mode, Mode>(ref instance.CurrentMode)/*cast due to .constrained prefix*/).ToString() + ", type=" + ((object)Unsafe.As<TYPES, TYPES>(ref instance.StructureType)/*cast due to .constrained prefix*/).ToString() + ", edit=" + IsEditBuildingsMode(instance) + ", cached=" + _hasCachedBuildMode + ", remembered=" + _hasLastBuildSelection + "."));
			if (IsEditBuildingsMode(instance))
			{
				if (!_hasCachedBuildMode && _hasLastBuildSelection)
				{
					_cachedBuildType = _lastBuildType;
					_cachedPlacementPrefab = _lastBuildPlacementPrefab;
					_cachedBuildMode = _lastBuildMode;
					_hasCachedBuildMode = true;
				}
				if (_hasCachedBuildMode)
				{
					SwitchToBuildMode(instance);
				}
				else
				{
					OpenBuildCatalogueFromEditMode(instance);
				}
			}
			else
			{
				SwitchToEditMode(instance);
			}
		}

		private void SwitchToEditMode(PlacementRegion region)
		{
			//IL_000a: 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_0018: Invalid comparison between Unknown and I4
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Invalid comparison between Unknown and I4
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_00cc: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: 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)
			if ((Object)(object)region == (Object)null || (int)region.CurrentMode == 0 || (int)region.CurrentMode == 3 || (int)region.CurrentMode == 4 || (int)region.CurrentMode == 2)
			{
				return;
			}
			_cachedBuildType = region.StructureType;
			_cachedPlacementPrefab = region.PlacementGameObject;
			_cachedBuildMode = region.CurrentMode;
			_hasCachedBuildMode = (int)_cachedBuildType != 0 && (int)_cachedBuildType != 215 && (Object)(object)_cachedPlacementPrefab != (Object)null;
			if (!_hasCachedBuildMode)
			{
				Log.LogWarning((object)"Could not cache the active building before entering Edit mode.");
				return;
			}
			_hasLastBuildSelection = true;
			_lastBuildType = _cachedBuildType;
			_lastBuildPlacementPrefab = _cachedPlacementPrefab;
			_lastBuildMode = _cachedBuildMode;
			Vector3 val = (((Object)(object)PlacementObject.Instance != (Object)null) ? ((Component)PlacementObject.Instance).transform.position : region.PlacementPosition);
			if (val == Vector3.zero && (Object)(object)PlayerFarming.Instance != (Object)null)
			{
				val = ((Component)PlayerFarming.Instance).transform.position;
			}
			try
			{
				HideModePrompt();
				PreserveCachedModeDuringTransition();
				PrepareRegionForModeSwitch(region, enteringEditMode: true);
				region.StructureType = (TYPES)215;
				region.PlacementGameObject = TypeAndPlacementObjects.GetByType((TYPES)215).PlacementObject;
				region.CurrentMode = (Mode)3;
				region.Play(val);
				Log.LogInfo((object)"Switched active placement to Edit Buildings mode.");
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Could not switch active placement to Edit Buildings mode: " + ex.Message));
			}
		}

		private void SwitchToBuildMode(PlacementRegion region)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			//IL_003e: 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)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Invalid comparison between Unknown and I4
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			if (!_hasCachedBuildMode || (int)_cachedBuildType == 0 || (int)_cachedBuildType == 215)
			{
				Log.LogInfo((object)"Build mode toggle ignored because there is no previous building selection to restore.");
				return;
			}
			GameObject val = _cachedPlacementPrefab;
			if ((Object)(object)val == (Object)null)
			{
				TypeAndPlacementObject byType = TypeAndPlacementObjects.GetByType(_cachedBuildType);
				val = ((byType != null) ? byType.PlacementObject : null);
			}
			if ((Object)(object)val == (Object)null)
			{
				Log.LogWarning((object)"Could not restore Build mode because the cached placement prefab is unavailable.");
				return;
			}
			Vector3 val2 = (((Object)(object)PlacementObject.Instance != (Object)null) ? ((Component)PlacementObject.Instance).transform.position : region.PlacementPosition);
			if (val2 == Vector3.zero)
			{
				val2 = GameManager.GetInstance().CamFollowTarget.GetCameraTargetWorldPosition();
			}
			try
			{
				HideModePrompt();
				PreserveCachedModeDuringTransition();
				PrepareRegionForModeSwitch(region, enteringEditMode: false);
				region.StructureType = _cachedBuildType;
				region.PlacementGameObject = val;
				region.CurrentMode = (Mode)(((int)_cachedBuildMode == 1) ? 1 : 5);
				region.Play(val2);
				Log.LogInfo((object)("Restored Build mode with " + ((object)Unsafe.As<TYPES, TYPES>(ref _cachedBuildType)/*cast due to .constrained prefix*/).ToString() + "."));
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Could not restore Build mode: " + ex.Message));
			}
		}

		private void OpenBuildCatalogueFromEditMode(PlacementRegion region)
		{
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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)
			if ((Object)(object)region == (Object)null || (Object)(object)MonoSingleton<UIManager>.Instance == (Object)null || (Object)(object)MonoSingleton<UIManager>.Instance.BuildMenuTemplate == (Object)null)
			{
				Log.LogWarning((object)"Could not return to the build catalogue because the build menu is unavailable.");
				return;
			}
			try
			{
				((MonoBehaviour)region).StopAllCoroutines();
				DestroyPlacementTiles(region);
				ClearPrefabsMethod?.Invoke(region, null);
				DestroyPrivateObject<PlacementObject>(region, PlacementObjectField);
				DestroyPrivateObject<PlacementObjectUI>(region, PlacementUiField);
				TilesInitiatedField?.SetValue(region, false);
				IsEditingBuildingsField?.SetValue(region, false);
				CurrentStructureToMoveField?.SetValue(region, null);
				CurrentStructureToUpgradeField?.SetValue(region, null);
				region.StructureType = (TYPES)0;
				region.CurrentMode = (Mode)0;
				region.PlacementPosition = Vector3.zero;
				GameManager.overridePlayerPosition = false;
				ClearCachedBuildMode();
				HideModePrompt();
				HideCancelPrompt();
				Time.timeScale = 0f;
				MonoSingleton<UIManager>.Instance.ShowBuildMenu((TYPES)0);
				Log.LogInfo((object)"Returned from externally opened Edit Buildings mode to the build catalogue.");
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Could not return from Edit Buildings mode to the build catalogue: " + ex.Message));
			}
		}

		private static void PrepareRegionForModeSwitch(PlacementRegion region, bool enteringEditMode)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			((MonoBehaviour)region).StopAllCoroutines();
			DestroyPlacementTiles(region);
			ClearPrefabsMethod?.Invoke(region, null);
			TilesInitiatedField?.SetValue(region, false);
			IsEditingBuildingsField?.SetValue(region, enteringEditMode);
			PreviousEditingPositionField?.SetValue(region, Vector3.zero);
			CurrentStructureToMoveField?.SetValue(region, null);
			CurrentStructureToUpgradeField?.SetValue(region, null);
		}

		private static void DestroyPlacementTiles(PlacementRegion region)
		{
			if (!(TilesField?.GetValue(region) is List<PlacementTile> list))
			{
				return;
			}
			PlacementTile[] array = list.ToArray();
			foreach (PlacementTile val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
			}
			list.Clear();
		}

		private static void DestroyPrivateObject<T>(PlacementRegion region, FieldInfo field) where T : Component
		{
			object? obj = field?.GetValue(region);
			T val = (T)((obj is T) ? obj : null);
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val).gameObject);
				field.SetValue(region, null);
			}
		}

		private void UpdateEditModePrompt()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Invalid comparison between Unknown and I4
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Invalid comparison between Unknown and I4
			if (!RemoteBuildCancelConfig.ShowEditModePrompt.Value || !RemoteBuildCancelConfig.Enabled.Value || !RemoteBuildCancelConfig.EnableEditModeToggle.Value || (Object)(object)PlacementRegion.Instance == (Object)null || (Object)(object)PlayerFarming.Instance == (Object)null || (Object)(object)PlayerFarming.Instance.indicator == (Object)null || !IsActiveBuildPlacement())
			{
				HideModePrompt();
				return;
			}
			Mode currentMode = PlacementRegion.Instance.CurrentMode;
			bool flag = IsEditBuildingsMode(PlacementRegion.Instance);
			if (!flag && (int)currentMode != 1 && (int)currentMode != 5)
			{
				HideModePrompt();
				return;
			}
			Indicator indicator = PlayerFarming.Instance.indicator;
			if (EnsureModePrompt(indicator))
			{
				_modeControlPrompt.playerFarming = PlayerFarming.Instance;
				bool flag2 = IsControllerInput();
				_modeControlPrompt.PrioritizeMouse = false;
				_modePromptText.text = (flag ? "Build" : "Edit");
				_modePromptCellObject.SetActive(true);
				SizePromptRow(_promptRowObject);
				_promptRowObject.SetActive(true);
				_modePromptObject.SetActive(true);
				_modePromptTextObject.SetActive(true);
				if (_modePromptWasController != flag2)
				{
					_modePromptWasController = flag2;
					RefreshModePromptGlyph(flag2);
				}
			}
		}

		private bool EnsureModePrompt(Indicator indicator)
		{
			if ((Object)(object)_promptOwner != (Object)null && (Object)(object)_promptOwner != (Object)(object)indicator)
			{
				DestroyAllPromptUi();
			}
			if ((Object)(object)_promptOwner == (Object)(object)indicator && (Object)(object)_modePromptCellObject != (Object)null && (Object)(object)_modeControlPrompt != (Object)null && (Object)(object)_modePromptText != (Object)null)
			{
				return true;
			}
			EnsurePromptRow(indicator);
			if ((Object)(object)_promptRowObject == (Object)null)
			{
				return false;
			}
			CreatePromptCell(indicator, "RemoteBuildCancel_ModeToggleCell", 120f, out _modePromptCellObject, out _modePromptObject, out _modeControlPrompt, out _modePromptTextObject, out _modePromptText);
			if ((Object)(object)_modeControlPrompt == (Object)null || (Object)(object)_modePromptText == (Object)null)
			{
				DestroyModePrompt();
				return false;
			}
			_modePromptWasController = null;
			return true;
		}

		private void RefreshModePromptGlyph(bool controller)
		{
			if (!((Object)(object)_modeControlPrompt == (Object)null))
			{
				if (controller)
				{
					_modeControlPrompt.IgnoreControllerChange = false;
					_modeControlPrompt.Category = 1;
					_modeControlPrompt.Action = 51;
					_modeControlPrompt.ForceUpdate();
				}
				else
				{
					SetCustomPromptKey(_modeControlPrompt, "C");
				}
			}
		}

		private void UpdateCancelPrompt()
		{
			if (!RemoteBuildCancelConfig.ShowCancelPrompt.Value || !RemoteBuildCancelConfig.Enabled.Value || !IsActiveBuildPlacement() || (Object)(object)PlayerFarming.Instance == (Object)null || (Object)(object)PlayerFarming.Instance.indicator == (Object)null)
			{
				HideCancelPrompt();
				return;
			}
			Structure val = GetHoveredStructure();
			if ((Object)(object)val == (Object)null && RemoteBuildCancelConfig.FallbackToLastPlaced.Value)
			{
				val = FindStructureById(_lastBuiltId);
			}
			if (!CanRemoteCancel(val))
			{
				HideCancelPrompt();
				return;
			}
			Indicator indicator = PlayerFarming.Instance.indicator;
			if (EnsureCancelPrompt(indicator))
			{
				bool flag = IsControllerInput();
				_cancelControlPrompt.playerFarming = PlayerFarming.Instance;
				_cancelControlPrompt.PrioritizeMouse = false;
				_cancelPromptText.text = "Cancel Build";
				_cancelPromptCellObject.SetActive(true);
				SizePromptRow(_promptRowObject);
				_promptRowObject.SetActive(true);
				_cancelPromptObject.SetActive(true);
				_cancelPromptTextObject.SetActive(true);
				if (_cancelPromptWasController != flag)
				{
					_cancelPromptWasController = flag;
					RefreshCancelPromptGlyph(flag);
				}
			}
		}

		private bool EnsureCancelPrompt(Indicator indicator)
		{
			if ((Object)(object)_promptOwner != (Object)null && (Object)(object)_promptOwner != (Object)(object)indicator)
			{
				DestroyAllPromptUi();
			}
			if ((Object)(object)_promptOwner == (Object)(object)indicator && (Object)(object)_cancelPromptCellObject != (Object)null && (Object)(object)_cancelControlPrompt != (Object)null && (Object)(object)_cancelPromptText != (Object)null)
			{
				return true;
			}
			EnsurePromptRow(indicator);
			if ((Object)(object)_promptRowObject == (Object)null)
			{
				return false;
			}
			CreatePromptCell(indicator, "RemoteBuildCancel_CancelCell", 165f, out _cancelPromptCellObject, out _cancelPromptObject, out _cancelControlPrompt, out _cancelPromptTextObject, out _cancelPromptText);
			if ((Object)(object)_cancelControlPrompt == (Object)null || (Object)(object)_cancelPromptText == (Object)null)
			{
				DestroyCancelPrompt();
				return false;
			}
			_cancelPromptWasController = null;
			return true;
		}

		private void EnsurePromptRow(Indicator indicator)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			if ((Object)(object)_promptRowObject != (Object)null && (Object)(object)_promptOwner == (Object)(object)indicator)
			{
				return;
			}
			Transform promptParent = GetPromptParent(indicator);
			if (!((Object)(object)promptParent == (Object)null))
			{
				Transform val = promptParent.Find("RemoteBuildCancel_BuilderToolsPromptRow");
				if ((Object)(object)val != (Object)null)
				{
					EnsureExistingPromptRow(((Component)val).gameObject, indicator);
					_promptOwner = indicator;
					_promptRowObject = ((Component)val).gameObject;
					return;
				}
				GameObject val2 = new GameObject("RemoteBuildCancel_BuilderToolsPromptRow");
				((Transform)val2.AddComponent<RectTransform>()).SetParent(promptParent, false);
				ConfigurePromptRow(val2);
				AddVanillaPromptBackground(val2, indicator);
				val2.transform.SetAsLastSibling();
				_promptOwner = indicator;
				_promptRowObject = val2;
			}
		}

		private static void ConfigurePromptRow(GameObject row)
		{
			//IL_001b: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Expected O, but got Unknown
			RectTransform obj = row.GetComponent<RectTransform>() ?? row.AddComponent<RectTransform>();
			obj.anchorMin = new Vector2(0.5f, 0f);
			obj.anchorMax = new Vector2(0.5f, 0f);
			obj.pivot = new Vector2(0f, 0f);
			obj.anchoredPosition = new Vector2(240f, 112f);
			obj.sizeDelta = new Vector2(0f, 52f);
			LayoutElement obj2 = row.GetComponent<LayoutElement>() ?? row.AddComponent<LayoutElement>();
			obj2.minWidth = 0f;
			obj2.preferredWidth = 0f;
			obj2.flexibleWidth = 0f;
			obj2.minHeight = 52f;
			obj2.preferredHeight = 52f;
			obj2.flexibleHeight = 0f;
			ContentSizeFitter obj3 = row.GetComponent<ContentSizeFitter>() ?? row.AddComponent<ContentSizeFitter>();
			obj3.horizontalFit = (FitMode)2;
			obj3.verticalFit = (FitMode)0;
			((Behaviour)obj3).enabled = false;
			HorizontalLayoutGroup obj4 = row.GetComponent<HorizontalLayoutGroup>() ?? row.AddComponent<HorizontalLayoutGroup>();
			((LayoutGroup)obj4).padding = new RectOffset(18, 18, 5, 5);
			((HorizontalOrVerticalLayoutGroup)obj4).spacing = 18f;
			((LayoutGroup)obj4).childAlignment = (TextAnchor)4;
			((HorizontalOrVerticalLayoutGroup)obj4).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj4).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj4).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj4).childForceExpandHeight = true;
		}

		private static void SizePromptRow(GameObject row)
		{
			//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)
			if ((Object)(object)row == (Object)null)
			{
				return;
			}
			RectTransform component = row.GetComponent<RectTransform>();
			HorizontalLayoutGroup component2 = row.GetComponent<HorizontalLayoutGroup>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
			{
				return;
			}
			float num = ((LayoutGroup)component2).padding.left + ((LayoutGroup)component2).padding.right;
			int num2 = 0;
			for (int i = 0; i < row.transform.childCount; i++)
			{
				GameObject gameObject = ((Component)row.transform.GetChild(i)).gameObject;
				if (!gameObject.activeSelf || ((Object)gameObject).name.IndexOf("VanillaPromptBackground", StringComparison.Ordinal) >= 0)
				{
					continue;
				}
				LayoutElement component3 = gameObject.GetComponent<LayoutElement>();
				float num3 = (((Object)(object)component3 != (Object)null) ? Mathf.Max(component3.minWidth, component3.preferredWidth) : 0f);
				if (num3 <= 0f)
				{
					RectTransform component4 = gameObject.GetComponent<RectTransform>();
					float num4;
					if (!((Object)(object)component4 != (Object)null))
					{
						num4 = 0f;
					}
					else
					{
						Rect rect = component4.rect;
						num4 = ((Rect)(ref rect)).width;
					}
					num3 = num4;
				}
				if (num3 <= 0f)
				{
					num3 = 40f;
				}
				if (num2 > 0)
				{
					num += ((HorizontalOrVerticalLayoutGroup)component2).spacing;
				}
				num += num3;
				num2++;
			}
			num = Mathf.Max(num, 1f);
			component.SetSizeWithCurrentAnchors((Axis)0, num);
			component.SetSizeWithCurrentAnchors((Axis)1, 52f);
			LayoutElement component5 = row.GetComponent<LayoutElement>();
			if ((Object)(object)component5 != (Object)null)
			{
				component5.minWidth = num;
				component5.preferredWidth = num;
			}
		}

		private static Transform GetPromptParent(Indicator indicator)
		{
			Transform val = (((Object)(object)indicator != (Object)null && (Object)(object)indicator.ControlPromptUI != (Object)null) ? indicator.ControlPromptUI.transform : (((Object)(object)indicator != (Object)null) ? ((Component)indicator).transform : null));
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Canvas val2 = ((Component)val).GetComponent<Canvas>() ?? ((Component)val).GetComponentInParent<Canvas>();
			if (!((Object)(object)val2 != (Object)null))
			{
				if (!((Object)(object)val.parent != (Object)null))
				{
					return val;
				}
				return val.parent;
			}
			return ((Component)val2).transform;
		}

		private static void EnsureExistingPromptRow(GameObject row, Indicator indicator)
		{
			if (!((Object)(object)row == (Object)null))
			{
				ConfigurePromptRow(row);
				AddVanillaPromptBackground(row, indicator);
			}
		}

		private static void AddVanillaPromptBackground(GameObject row, Indicator indicator)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			Image val = (((Object)(object)indicator != (Object)null && (Object)(object)indicator.BG != (Object)null) ? (((Component)indicator.BG).GetComponent<Image>() ?? ((Component)indicator.BG).GetComponentInChildren<Image>(true)) : null);
			Image val2 = row.GetComponent<Image>() ?? row.AddComponent<Image>();
			((Behaviour)val2).enabled = true;
			((Graphic)val2).raycastTarget = false;
			val2.sprite = (((Object)(object)val != (Object)null) ? val.sprite : null);
			val2.type = (Type)(((Object)(object)val != (Object)null) ? ((int)val.type) : 0);
			if ((Object)(object)val2.sprite == (Object)null)
			{
				val2.sprite = Sprite.Create(Texture2D.whiteTexture, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f));
				val2.type = (Type)0;
			}
			((Graphic)val2).color = new Color(0f, 0f, 0f, 0.88f);
			((Graphic)val2).canvasRenderer.SetColor(((Graphic)val2).color);
			for (int i = 0; i < row.transform.childCount; i++)
			{
				Transform child = row.transform.GetChild(i);
				if (((Object)child).name.IndexOf("VanillaPromptBackground", StringComparison.Ordinal) >= 0)
				{
					((Component)child).gameObject.SetActive(false);
				}
			}
		}

		private void CreatePromptCell(Indicator indicator, string cellName, float preferredWidth, out GameObject cellObject, out GameObject promptObject, out MMControlPrompt controlPrompt, out GameObject textObject, out TMP_Text promptText)
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			cellObject = null;
			promptObject = null;
			controlPrompt = null;
			textObject = null;
			promptText = null;
			RectTransform val = (((Object)(object)indicator.FourthControlPrompt != (Object)null) ? indicator.FourthControlPrompt : indicator.ThirdControlPrompt);
			if ((Object)(object)val == (Object)null)
			{
				val = (((Object)(object)indicator.SecondaryControlPrompt != (Object)null) ? indicator.SecondaryControlPrompt : indicator.ControlPrompt);
			}
			TMP_Text val2 = (TMP_Text)(object)(((Object)(object)indicator.Fourthtext != (Object)null) ? indicator.Fourthtext : indicator.Thirdtext);
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = (TMP_Text)(object)(((Object)(object)indicator.SecondaryText != (Object)null) ? indicator.SecondaryText : indicator.text);
			}
			if ((Object)(object)_promptRowObject == (Object)null || (Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				return;
			}
			GameObject val3 = new GameObject(cellName);
			((Transform)val3.AddComponent<RectTransform>()).SetParent(_promptRowObject.transform, false);
			LayoutElement obj = val3.AddComponent<LayoutElement>();
			obj.preferredWidth = preferredWidth;
			obj.minWidth = preferredWidth;
			HorizontalLayoutGroup obj2 = val3.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj2).spacing = 6f;
			((LayoutGroup)obj2).childAlignment = (TextAnchor)4;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = true;
			GameObject val4 = Object.Instantiate<GameObject>(((Component)val).gameObject, val3.transform, false);
			((Object)val4).name = cellName + "_Key";
			val4.SetActive(true);
			val4.transform.localScale = Vector3.one;
			controlPrompt = val4.GetComponent<MMControlPrompt>() ?? val4.GetComponentInChildren<MMControlPrompt>(true);
			LayoutElement obj3 = val4.GetComponent<LayoutElement>() ?? val4.AddComponent<LayoutElement>();
			obj3.preferredWidth = 50f;
			obj3.minWidth = 42f;
			obj3.preferredHeight = 40f;
			TMP_Text val5 = Object.Instantiate<TMP_Text>(val2, val3.transform, false);
			((Object)((Component)val5).gameObject).name = cellName + "_Label";
			((Component)val5).gameObject.SetActive(true);
			val5.transform.localScale = Vector3.one;
			val5.alignment = (TextAlignmentOptions)4097;
			val5.enableAutoSizing = true;
			val5.fontSizeMin = 12f;
			val5.fontSizeMax = 22f;
			LayoutElement obj4 = ((Component)val5).GetComponent<LayoutElement>() ?? ((Component)val5).gameObject.AddComponent<LayoutElement>();
			obj4.preferredWidth = preferredWidth - 58f;
			obj4.minWidth = preferredWidth - 58f;
			Behaviour[] components = ((Component)val5).GetComponents<Behaviour>();
			foreach (Behaviour val6 in components)
			{
				if ((Object)(object)val6 != (Object)null && ((object)val6).GetType().FullName == "I2.Loc.Localize")
				{
					val6.enabled = false;
				}
			}
			cellObject = val3;
			promptObject = val4;
			textObject = ((Component)val5).gameObject;
			promptText = val5;
		}

		private void RefreshCancelPromptGlyph(bool controller)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_cancelControlPrompt == (Object)null))
			{
				SetCustomPromptKey(_cancelControlPrompt, controller ? ControllerButtonLabel(_controllerCancelKey) : "MMB");
			}
		}

		private static void SetCustomPromptKey(MMControlPrompt prompt, string label)
		{
			prompt.IgnoreControllerChange = true;
			object? obj = AccessTools.Field(typeof(MMControlPrompt), "_text")?.GetValue(prompt);
			TMP_Text val = (TMP_Text)((obj is TMP_Text) ? obj : null);
			object? obj2 = AccessTools.Field(typeof(MMControlPrompt), "_iconText")?.GetValue(prompt);
			TMP_Text val2 = (TMP_Text)((obj2 is TMP_Text) ? obj2 : null);
			object? obj3 = AccessTools.Field(typeof(MMControlPrompt), "_icon")?.GetValue(prompt);
			Image val3 = (Image)((obj3 is Image) ? obj3 : null);
			if ((Object)(object)val != (Object)null)
			{
				val.text = label;
				val.fontSize = 20f;
				val.enableAutoSizing = true;
				val.fontSizeMin = 8f;
				val.fontSizeMax = 20f;
				((Component)val).gameObject.SetActive(true);
			}
			if ((Object)(object)val2 != (Object)null)
			{
				((Component)val2).gameObject.SetActive(false);
			}
			if ((Object)(object)val3 != (Object)null)
			{
				((Component)val3).gameObject.SetActive(true);
			}
		}

		private void HideCancelPrompt()
		{
			if ((Object)(object)_cancelPromptCellObject != (Object)null)
			{
				_cancelPromptCellObject.SetActive(false);
			}
			RefreshPromptRowVisibility(_promptRowObject);
		}

		private void DestroyCancelPrompt()
		{
			if ((Object)(object)_cancelPromptCellObject != (Object)null)
			{
				Object.Destroy((Object)(object)_cancelPromptCellObject);
			}
			else
			{
				if ((Object)(object)_cancelPromptObject != (Object)null)
				{
					Object.Destroy((Object)(object)_cancelPromptObject);
				}
				if ((Object)(object)_cancelPromptTextObject != (Object)null)
				{
					Object.Destroy((Object)(object)_cancelPromptTextObject);
				}
			}
			_cancelPromptCellObject = null;
			_cancelPromptObject = null;
			_cancelPromptTextObject = null;
			_cancelControlPrompt = null;
			_cancelPromptText = null;
			_cancelPromptWasController = null;
		}

		private void HideModePrompt()
		{
			if ((Object)(object)_modePromptCellObject != (Object)null && _modePromptCellObject.activeSelf)
			{
				_modePromptCellObject.SetActive(false);
			}
			RefreshPromptRowVisibility(_promptRowObject);
		}

		private static void RefreshPromptRowVisibility(GameObject row)
		{
			if ((Object)(object)row == (Object)null)
			{
				return;
			}
			bool active = false;
			for (int i = 0; i < row.transform.childCount; i++)
			{
				GameObject gameObject = ((Component)row.transform.GetChild(i)).gameObject;
				if (gameObject.activeSelf && ((Object)gameObject).name.IndexOf("VanillaPromptBackground", StringComparison.Ordinal) < 0)
				{
					active = true;
					break;
				}
			}
			SizePromptRow(row);
			row.SetActive(active);
		}

		private void DestroyModePrompt()
		{
			if ((Object)(object)_modePromptCellObject != (Object)null)
			{
				Object.Destroy((Object)(object)_modePromptCellObject);
			}
			else
			{
				if ((Object)(object)_modePromptObject != (Object)null)
				{
					Object.Destroy((Object)(object)_modePromptObject);
				}
				if ((Object)(object)_modePromptTextObject != (Object)null)
				{
					Object.Destroy((Object)(object)_modePromptTextObject);
				}
			}
			_modePromptCellObject = null;
			_modePromptObject = null;
			_modePromptTextObject = null;
			_modeControlPrompt = null;
			_modePromptText = null;
			_modePromptWasController = null;
		}

		private void DestroyAllPromptUi()
		{
			DestroyModePrompt();
			DestroyCancelPrompt();
			if ((Object)(object)_promptRowObject != (Object)null)
			{
				Object.Destroy((Object)(object)_promptRowObject);
			}
			_promptRowObject = null;
			_promptOwner = null;
		}

		private static bool IsControllerInput()
		{
			try
			{
				return (Object)(object)PlayerFarming.Instance != (Object)null && InputManager.General.InputIsController(PlayerFarming.Instance);
			}
			catch
			{
				return false;
			}
		}

		private bool CanRemoteCancel(Structure target)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)target == (Object)null || target.Brain == null || target.Brain.Data == null)
			{
				return false;
			}
			if (RemoteBuildCancelConfig.OnlyCancelBuildSites.Value && !IsBuildSite(target.Brain.Data.Type))
			{
				return false;
			}
			if (!RemoteBuildCancelConfig.AllowCriticalStructures.Value)
			{
				return !IsCritical(target.Brain.Data.Type);
			}
			return true;
		}

		private unsafe static string ControllerButtonLabel(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected I4, but got Unknown
			return (key - 330) switch
			{
				0 => "A", 
				1 => "B", 
				2 => "X", 
				3 => "Y", 
				4 => "LB", 
				5 => "RB", 
				6 => "Back", 
				7 => "Start", 
				8 => "LS", 
				9 => "RS", 
				_ => ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString().Replace("JoystickButton", "Pad "), 
			};
		}

		private void ClearCachedBuildMode()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			_hasCachedBuildMode = false;
			_cachedBuildType = (TYPES)0;
			_cachedPlacementPrefab = null;
			_cachedBuildMode = (Mode)5;
			_preserveCachedModeUntil = 0f;
		}

		private void PreserveCachedModeDuringTransition()
		{
			_preserveCachedModeUntil = Time.unscaledTime + 0.75f;
		}

		private void RememberActiveBuildSelection()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Invalid comparison between Unknown and I4
			//IL_004f: 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_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)
			PlacementRegion instance = PlacementRegion.Instance;
			if (!((Object)(object)instance == (Object)null) && ((int)instance.CurrentMode == 1 || (int)instance.CurrentMode == 5) && (int)instance.StructureType != 0 && (int)instance.StructureType != 215 && !((Object)(object)instance.PlacementGameObject == (Object)null))
			{
				_hasLastBuildSelection = true;
				_lastBuildType = instance.StructureType;
				_lastBuildPlacementPrefab = instance.PlacementGameObject;
				_lastBuildMode = instance.CurrentMode;
			}
		}

		internal void RememberLatest(StructureBrain brain)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (brain != null && brain.Data != null && IsActiveBuildPlacement() && (!RemoteBuildCancelConfig.OnlyCancelBuildSites.Value || IsBuildSite(brain.Data.Type)))
			{
				_lastBuiltId = brain.Data.ID;
			}
		}

		private static Structure GetHoveredStructure()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			Structure val = (((Object)(object)PlacementRegion.Instance != (Object)null) ? PlacementRegion.Instance.GetHoveredStructure() : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			if ((Object)(object)PlacementRegion.Instance != (Object)null)
			{
				return GetNearestStructureAtPlacement(PlacementRegion.Instance.PlacementPosition, RemoteBuildCancelConfig.TargetRadius.Value);
			}
			return null;
		}

		private static Structure GetNearestStructureAtPlacement(Vector3 position, float radius)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			Structure result = null;
			float num = radius;
			Structure[] array = Structure.Structures.ToArray();
			foreach (Structure val in array)
			{
				if (!((Object)(object)val == (Object)null) && val.Brain != null && val.Brain.Data != null)
				{
					float num2 = Vector3.Distance(position, ((Component)val).transform.position);
					if (num2 <= num)
					{
						result = val;
						num = num2;
					}
				}
			}
			return result;
		}

		private static Structure FindStructureById(int id)
		{
			if (id < 0)
			{
				return null;
			}
			Structure[] array = Structure.Structures.ToArray();
			foreach (Structure val in array)
			{
				if ((Object)(object)val != (Object)null && val.Brain != null && val.Brain.Data != null && val.Brain.Data.ID == id)
				{
					return val;
				}
			}
			return null;
		}

		private static bool RemoveStructureCleanly(Structure structure)
		{
			//IL_002b: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)structure == (Object)null || structure.Brain == null || structure.Brain.Data == null)
			{
				return false;
			}
			TYPES type = structure.Brain.Data.Type;
			TYPES toBuildType = structure.Brain.Data.ToBuildType;
			try
			{
				if ((Object)(object)PlacementRegion.Instance != (Object)null)
				{
					PlacementRegion.Instance.DestroyBuilding(structure);
				}
				else
				{
					structure.RemoveStructure();
					Object.Destroy((Object)(object)((Component)structure).gameObject);
				}
				RefundBuildSiteMaterials(type, toBuildType);
				return true;
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Remote cancel clean removal failed: " + ex.Message));
				return false;
			}
		}

		private static void RefundBuildSiteMaterials(TYPES type, TYPES toBuildType)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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)
			if (!IsBuildSite(type))
			{
				return;
			}
			List<ItemCost> cost = StructuresData.GetCost(((int)toBuildType != 0) ? toBuildType : type);
			if (cost == null)
			{
				return;
			}
			for (int i = 0; i < cost.Count; i++)
			{
				ItemCost val = cost[i];
				if (val.CostValue > 0)
				{
					Inventory.AddItem(val.CostItem, val.CostValue, true);
				}
			}
			RefreshPlacementCostUi();
		}

		private static void RefreshPlacementCostUi()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			PlacementRegion instance = PlacementRegion.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			try
			{
				object? obj = PlacementUiField?.GetValue(instance);
				PlacementObjectUI val = (PlacementObjectUI)((obj is PlacementObjectUI) ? obj : null);
				if ((Object)(object)val != (Object)null)
				{
					val.UpdateText(instance.StructureType);
				}
			}
			catch (Exception ex)
			{
				Log.LogDebug((object)("Could not refresh live placement cost UI: " + ex.Message));
			}
		}

		private static bool IsActiveBuildPlacement()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Invalid comparison between Unknown and I4
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Invalid comparison between Unknown and I4
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Invalid comparison between Unknown and I4
			PlacementRegion instance = PlacementRegion.Instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)PlacementObject.Instance == (Object)null)
			{
				return false;
			}
			if (IsEditBuildingsMode(instance))
			{
				return true;
			}
			if ((int)instance.CurrentMode == 0)
			{
				return false;
			}
			Mode currentMode = instance.CurrentMode;
			if ((int)currentMode != 1 && (int)currentMode != 5)
			{
				return (int)currentMode == 3;
			}
			return true;
		}

		private static bool IsEditBuildingsMode(PlacementRegion region)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Invalid comparison between Unknown and I4
			if ((Object)(object)region == (Object)null)
			{
				return false;
			}
			if ((int)region.StructureType == 215)
			{
				return true;
			}
			try
			{
				if (IsEditingBuildingsField != null && (bool)IsEditingBuildingsField.GetValue(region))
				{
					return true;
				}
			}
			catch
			{
			}
			return (int)region.CurrentMode == 3;
		}

		private static bool IsBuildSite(TYPES type)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)type != 31)
			{
				return (int)type == 118;
			}
			return true;
		}

		private unsafe static bool IsCritical(TYPES type)
		{
			string text = ((object)(*(TYPES*)(&type))/*cast due to .constrained prefix*/).ToString();
			if (!text.Contains("TEMPLE") && !text.Contains("SHRINE") && !text.Contains("ALTAR"))
			{
				return text.Contains("BUILDER");
			}
			return true;
		}

		private static KeyCode ParseKey(string raw, KeyCode fallback)
		{
			//IL_0011: 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_001a: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return (KeyCode)Enum.Parse(typeof(KeyCode), raw, ignoreCase: true);
			}
			catch
			{
				return fallback;
			}
		}
	}
	internal static class RemoteBuildCancelConfig
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<string> CancelKey;

		internal static ConfigEntry<string> MouseCancelKey;

		internal static ConfigEntry<bool> EnableControllerCancel;

		internal static ConfigEntry<string> ControllerCancelKey;

		internal static ConfigEntry<bool> EnableEditModeToggle;

		internal static ConfigEntry<bool> UseVanillaEditModeAction;

		internal static ConfigEntry<string> EditModeKey;

		internal static ConfigEntry<bool> ShowEditModePrompt;

		internal static ConfigEntry<bool> ShowCancelPrompt;

		internal static ConfigEntry<bool> OnlyCancelBuildSites;

		internal static ConfigEntry<bool> FallbackToLastPlaced;

		internal static ConfigEntry<bool> AllowCriticalStructures;

		internal static ConfigEntry<float> TargetRadius;

		internal static void Bind(ConfigFile config)
		{
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Expected O, but got Unknown
			Enabled = config.Bind<bool>("General", "Enabled", true, "Enable Remote Build Cancel.");
			CancelKey = config.Bind<string>("Controls", "CancelKey", "F9", "KeyCode used to cancel the hovered or latest placed structure.");
			MouseCancelKey = config.Bind<string>("Controls", "MouseCancelKey", "Mouse2", "Mouse KeyCode used to cancel the hovered or latest placed structure. Mouse2 is middle mouse.");
			EnableControllerCancel = config.Bind<bool>("Controls", "EnableControllerCancel", true, "Enable the configured controller KeyCode for canceling the hovered or latest placed structure.");
			ControllerCancelKey = config.Bind<string>("Controls", "ControllerCancelKey", "JoystickButton2", "Controller KeyCode used to cancel the hovered or latest placed structure.");
			EnableEditModeToggle = config.Bind<bool>("Controls", "EnableEditModeToggle", true, "Allow switching from active placement into Edit Buildings mode without reopening the build catalogue.");
			UseVanillaEditModeAction = config.Bind<bool>("Controls", "UseVanillaEditModeAction", true, "Use the game's normal Edit Buildings input action while actively placing a structure.");
			EditModeKey = config.Bind<string>("Controls", "EditModeKey", "F7", "Fallback keyboard KeyCode used to switch active placement into Edit Buildings mode.");
			ShowEditModePrompt = config.Bind<bool>("UI", "ShowEditModePrompt", true, "Show a vanilla bottom-bar prompt for switching active placement into Edit Buildings mode.");
			ShowCancelPrompt = config.Bind<bool>("UI", "ShowCancelPrompt", true, "Show a vanilla bottom-bar prompt for the middle-mouse or controller remote-cancel action.");
			OnlyCancelBuildSites = config.Bind<bool>("Behavior", "OnlyCancelBuildSites", true, "Only allow remote cancel for unbuilt BUILD_SITE / BUILDSITE_BUILDINGPROJECT structures.");
			FallbackToLastPlaced = config.Bind<bool>("Behavior", "FallbackToLastPlaced", true, "Cancel the most recently placed structure if no hovered structure is found.");
			AllowCriticalStructures = config.Bind<bool>("Safety", "AllowCriticalStructures", false, "Allow remote cancel for temple/shrine/altar/builder style critical structures.");
			TargetRadius = config.Bind<float>("Targeting", "TargetRadius", 1.25f, new ConfigDescription("Fallback radius around the build cursor when vanilla hover targeting returns nothing.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 5f), Array.Empty<object>()));
		}
	}
	[HarmonyPatch(typeof(StructureManager), "AddStructure")]
	internal static class StructureManagerAddStructurePatch
	{
		private static void Postfix(StructureBrain __result)
		{
			RemoteBuildCancelPlugin.Instance?.RememberLatest(__result);
		}
	}
}

plugins/BetterBuilderTools/UndoBuildAction.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using MMTools;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Undo Build Action")]
[assembly: AssemblyProduct("Undo Build Action")]
[assembly: ComVisible(false)]
[assembly: Guid("eac82e42-17ee-466e-a457-6b853a2699ca")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyVersion("0.2.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace UndoBuildAction
{
	[BepInPlugin("com.cotl.betterbuildertools.undobuildaction", "Undo Build Action", "0.2.1")]
	public sealed class UndoBuildActionPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.cotl.betterbuildertools.undobuildaction";

		public const string PluginName = "Undo Build Action";

		public const string PluginVersion = "0.2.1";

		private readonly List<int> _undoStack = new List<int>();

		private Harmony _harmony;

		private KeyCode _undoKey;

		private Indicator _promptOwner;

		private GameObject _undoPromptObject;

		private GameObject _undoPromptTextObject;

		private MMControlPrompt _undoControlPrompt;

		private TMP_Text _undoPromptText;

		private GameObject _promptRowObject;

		private GameObject _undoPromptCellObject;

		private bool _promptCreationWarningLogged;

		private bool? _promptWasController;

		internal static ManualLogSource Log { get; private set; }

		internal static UndoBuildActionPlugin Instance { get; private set; }

		private void Awake()
		{
			//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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			UndoBuildActionConfig.Bind(((BaseUnityPlugin)this).Config);
			_undoKey = ParseKey(UndoBuildActionConfig.UndoKey.Value, (KeyCode)122);
			_harmony = new Harmony("com.cotl.betterbuildertools.undobuildaction");
			_harmony.PatchAll(typeof(UndoBuildActionPlugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Undo Build Action 0.2.1 loaded.");
		}

		private void OnDestroy()
		{
			DestroyUndoPrompt();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			Instance = null;
		}

		private void Update()
		{
			if (UndoBuildActionConfig.Enabled.Value && UndoPressed())
			{
				UndoLatest();
			}
		}

		private void LateUpdate()
		{
			UpdateUndoPrompt();
		}

		private bool UndoPressed()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(_undoKey))
			{
				if (UndoBuildActionConfig.RequireControl.Value && !Input.GetKey((KeyCode)306))
				{
					return Input.GetKey((KeyCode)305);
				}
				return true;
			}
			if (!UndoBuildActionConfig.EnableControllerUndo.Value)
			{
				return false;
			}
			try
			{
				PlayerFarming instance = PlayerFarming.Instance;
				return (Object)(object)instance != (Object)null && InputManager.General.InputIsController(instance) && InputManager.UI.GetPageNavigateLeftDown(instance);
			}
			catch
			{
				return false;
			}
		}

		internal void RecordLatest(StructureBrain brain)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (brain != null && brain.Data != null && IsInPlacementFlow() && (UndoBuildActionConfig.AllowCriticalStructures.Value || !IsCritical(brain.Data.Type)))
			{
				_undoStack.Add(brain.Data.ID);
				while (_undoStack.Count > UndoBuildActionConfig.UndoDepth.Value)
				{
					_undoStack.RemoveAt(0);
				}
			}
		}

		internal void ClearSession()
		{
			_undoStack.Clear();
			HideUndoPrompt();
		}

		private unsafe void UndoLatest()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			while (_undoStack.Count > 0)
			{
				int index = _undoStack.Count - 1;
				int id = _undoStack[index];
				_undoStack.RemoveAt(index);
				Structure val = FindStructureById(id);
				if ((Object)(object)val != (Object)null && val.Brain != null && val.Brain.Data != null)
				{
					TYPES type = val.Brain.Data.Type;
					if (RemoveStructureCleanly(val))
					{
						Log.LogInfo((object)("Undid placement of " + ((object)(*(TYPES*)(&type))/*cast due to .constrained prefix*/).ToString() + "."));
					}
					break;
				}
			}
		}

		private static Structure FindStructureById(int id)
		{
			Structure[] array = Structure.Structures.ToArray();
			foreach (Structure val in array)
			{
				if ((Object)(object)val != (Object)null && val.Brain != null && val.Brain.Data != null && val.Brain.Data.ID == id)
				{
					return val;
				}
			}
			return null;
		}

		private static bool RemoveStructureCleanly(Structure structure)
		{
			//IL_002b: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)structure == (Object)null || structure.Brain == null || structure.Brain.Data == null)
			{
				return false;
			}
			TYPES type = structure.Brain.Data.Type;
			TYPES toBuildType = structure.Brain.Data.ToBuildType;
			Vector3 position = ((Component)structure).transform.position;
			try
			{
				if ((Object)(object)PlacementRegion.Instance != (Object)null)
				{
					PlacementRegion.Instance.DestroyBuilding(structure);
				}
				else
				{
					structure.RemoveStructure();
					Object.Destroy((Object)(object)((Component)structure).gameObject);
				}
				RefundBuildSiteMaterials(type, toBuildType, position);
				return true;
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Undo clean removal failed: " + ex.Message));
				return false;
			}
		}

		private static void RefundBuildSiteMaterials(TYPES type, TYPES toBuildType, Vector3 position)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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)
			if ((int)type != 31 && (int)type != 118)
			{
				return;
			}
			List<ItemCost> cost = StructuresData.GetCost(((int)toBuildType != 0) ? toBuildType : type);
			if (cost == null)
			{
				return;
			}
			for (int i = 0; i < cost.Count; i++)
			{
				ItemCost val = cost[i];
				if (val.CostValue > 0)
				{
					InventoryItem.Spawn(val.CostItem, val.CostValue, position, 4f, (Action<PickUp>)null);
				}
			}
		}

		private static bool IsInPlacementFlow()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Invalid comparison between Unknown and I4
			if (!((Object)(object)PlacementObject.Instance != (Object)null))
			{
				if ((Object)(object)PlacementRegion.Instance != (Object)null)
				{
					return (int)PlacementRegion.Instance.CurrentMode > 0;
				}
				return false;
			}
			return true;
		}

		private unsafe static bool IsCritical(TYPES type)
		{
			string text = ((object)(*(TYPES*)(&type))/*cast due to .constrained prefix*/).ToString();
			if (!text.Contains("TEMPLE") && !text.Contains("SHRINE") && !text.Contains("ALTAR"))
			{
				return text.Contains("BUILDER");
			}
			return true;
		}

		private void UpdateUndoPrompt()
		{
			if (!UndoBuildActionConfig.ShowUndoPrompt.Value || !UndoBuildActionConfig.Enabled.Value || _undoStack.Count == 0 || !IsInPlacementFlow() || (Object)(object)PlayerFarming.Instance == (Object)null || (Object)(object)PlayerFarming.Instance.indicator == (Object)null)
			{
				HideUndoPrompt();
				return;
			}
			Indicator indicator = PlayerFarming.Instance.indicator;
			if (EnsureUndoPrompt(indicator))
			{
				bool flag = false;
				try
				{
					flag = InputManager.General.InputIsController(PlayerFarming.Instance);
				}
				catch
				{
				}
				_undoControlPrompt.playerFarming = PlayerFarming.Instance;
				_undoControlPrompt.PrioritizeMouse = false;
				_undoPromptCellObject.SetActive(true);
				SizePromptRow(_promptRowObject);
				_promptRowObject.SetActive(true);
				_undoPromptObject.SetActive(true);
				_undoPromptTextObject.SetActive(true);
				if (_promptWasController != flag)
				{
					_promptWasController = flag;
					RefreshPromptGlyph(flag);
				}
				_undoPromptText.text = "Undo";
			}
		}

		private bool EnsureUndoPrompt(Indicator indicator)
		{
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected O, but got Unknown
			//IL_0140: 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)
			if ((Object)(object)_promptOwner == (Object)(object)indicator && (Object)(object)_undoPromptCellObject != (Object)null && (Object)(object)_undoControlPrompt != (Object)null && (Object)(object)_undoPromptText != (Object)null)
			{
				return true;
			}
			DestroyUndoPrompt();
			if ((Object)(object)indicator.FourthControlPrompt == (Object)null || (Object)(object)((Transform)indicator.FourthControlPrompt).parent == (Object)null || (Object)(object)indicator.Fourthtext == (Object)null || (Object)(object)((TMP_Text)indicator.Fourthtext).transform.parent == (Object)null)
			{
				return false;
			}
			EnsurePromptRow(indicator);
			if ((Object)(object)_promptRowObject == (Object)null)
			{
				return false;
			}
			GameObject val = new GameObject("UndoBuildAction_UndoCell");
			((Transform)val.AddComponent<RectTransform>()).SetParent(_promptRowObject.transform, false);
			LayoutElement obj = val.AddComponent<LayoutElement>();
			obj.preferredWidth = 110f;
			obj.minWidth = 110f;
			HorizontalLayoutGroup obj2 = val.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj2).spacing = 6f;
			((LayoutGroup)obj2).childAlignment = (TextAnchor)4;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = true;
			GameObject val2 = Object.Instantiate<GameObject>(((Component)indicator.FourthControlPrompt).gameObject, val.transform, false);
			((Object)val2).name = "UndoBuildAction_UndoPrompt";
			val2.SetActive(true);
			val2.transform.localScale = Vector3.one;
			MMControlPrompt val3 = val2.GetComponent<MMControlPrompt>() ?? val2.GetComponentInChildren<MMControlPrompt>(true);
			LayoutElement obj3 = val2.GetComponent<LayoutElement>() ?? val2.AddComponent<LayoutElement>();
			obj3.preferredWidth = 50f;
			obj3.minWidth = 42f;
			obj3.preferredHeight = 40f;
			TMP_Text val4 = (TMP_Text)(object)Object.Instantiate<TextMeshProUGUI>(indicator.Fourthtext, val.transform, false);
			((Object)((Component)val4).gameObject).name = "UndoBuildAction_UndoText";
			((Component)val4).gameObject.SetActive(true);
			val4.transform.localScale = Vector3.one;
			val4.alignment = (TextAlignmentOptions)4097;
			val4.enableAutoSizing = true;
			val4.fontSizeMin = 12f;
			val4.fontSizeMax = 22f;
			LayoutElement obj4 = ((Component)val4).GetComponent<LayoutElement>() ?? ((Component)val4).gameObject.AddComponent<LayoutElement>();
			obj4.preferredWidth = 52f;
			obj4.minWidth = 52f;
			Behaviour[] components = ((Component)val4).GetComponents<Behaviour>();
			foreach (Behaviour val5 in components)
			{
				if ((Object)(object)val5 != (Object)null && ((object)val5).GetType().FullName == "I2.Loc.Localize")
				{
					val5.enabled = false;
				}
			}
			if ((Object)(object)val3 == (Object)null)
			{
				Object.Destroy((Object)(object)val);
				if (!_promptCreationWarningLogged)
				{
					_promptCreationWarningLogged = true;
					Log.LogWarning((object)"Could not create the standalone Undo control prompt.");
				}
				return false;
			}
			_promptOwner = indicator;
			_undoPromptCellObject = val;
			_undoPromptObject = val2;
			_undoPromptTextObject = ((Component)val4).gameObject;
			_undoControlPrompt = val3;
			_undoPromptText = val4;
			_promptCreationWarningLogged = false;
			_promptWasController = null;
			return true;
		}

		private void EnsurePromptRow(Indicator indicator)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			if ((Object)(object)_promptRowObject != (Object)null && (Object)(object)_promptOwner == (Object)(object)indicator)
			{
				return;
			}
			Transform promptParent = GetPromptParent(indicator);
			if (!((Object)(object)promptParent == (Object)null))
			{
				Transform val = promptParent.Find("RemoteBuildCancel_BuilderToolsPromptRow");
				if ((Object)(object)val != (Object)null)
				{
					ConfigurePromptRow(((Component)val).gameObject);
					AddVanillaPromptBackground(((Component)val).gameObject, indicator);
					_promptOwner = indicator;
					_promptRowObject = ((Component)val).gameObject;
				}
				else
				{
					GameObject val2 = new GameObject("RemoteBuildCancel_BuilderToolsPromptRow");
					((Transform)val2.AddComponent<RectTransform>()).SetParent(promptParent, false);
					ConfigurePromptRow(val2);
					AddVanillaPromptBackground(val2, indicator);
					val2.transform.SetAsLastSibling();
					_promptOwner = indicator;
					_promptRowObject = val2;
				}
			}
		}

		private static void ConfigurePromptRow(GameObject row)
		{
			//IL_001b: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Expected O, but got Unknown
			RectTransform obj = row.GetComponent<RectTransform>() ?? row.AddComponent<RectTransform>();
			obj.anchorMin = new Vector2(0.5f, 0f);
			obj.anchorMax = new Vector2(0.5f, 0f);
			obj.pivot = new Vector2(0f, 0f);
			obj.anchoredPosition = new Vector2(240f, 112f);
			obj.sizeDelta = new Vector2(0f, 52f);
			LayoutElement obj2 = row.GetComponent<LayoutElement>() ?? row.AddComponent<LayoutElement>();
			obj2.minWidth = 0f;
			obj2.preferredWidth = 0f;
			obj2.flexibleWidth = 0f;
			obj2.minHeight = 52f;
			obj2.preferredHeight = 52f;
			obj2.flexibleHeight = 0f;
			ContentSizeFitter obj3 = row.GetComponent<ContentSizeFitter>() ?? row.AddComponent<ContentSizeFitter>();
			obj3.horizontalFit = (FitMode)2;
			obj3.verticalFit = (FitMode)0;
			((Behaviour)obj3).enabled = false;
			HorizontalLayoutGroup obj4 = row.GetComponent<HorizontalLayoutGroup>() ?? row.AddComponent<HorizontalLayoutGroup>();
			((LayoutGroup)obj4).padding = new RectOffset(18, 18, 5, 5);
			((HorizontalOrVerticalLayoutGroup)obj4).spacing = 18f;
			((LayoutGroup)obj4).childAlignment = (TextAnchor)4;
			((HorizontalOrVerticalLayoutGroup)obj4).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj4).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj4).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj4).childForceExpandHeight = true;
		}

		private static void SizePromptRow(GameObject row)
		{
			//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)
			if ((Object)(object)row == (Object)null)
			{
				return;
			}
			RectTransform component = row.GetComponent<RectTransform>();
			HorizontalLayoutGroup component2 = row.GetComponent<HorizontalLayoutGroup>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
			{
				return;
			}
			float num = ((LayoutGroup)component2).padding.left + ((LayoutGroup)component2).padding.right;
			int num2 = 0;
			for (int i = 0; i < row.transform.childCount; i++)
			{
				GameObject gameObject = ((Component)row.transform.GetChild(i)).gameObject;
				if (!gameObject.activeSelf || ((Object)gameObject).name.IndexOf("VanillaPromptBackground", StringComparison.Ordinal) >= 0)
				{
					continue;
				}
				LayoutElement component3 = gameObject.GetComponent<LayoutElement>();
				float num3 = (((Object)(object)component3 != (Object)null) ? Mathf.Max(component3.minWidth, component3.preferredWidth) : 0f);
				if (num3 <= 0f)
				{
					RectTransform component4 = gameObject.GetComponent<RectTransform>();
					float num4;
					if (!((Object)(object)component4 != (Object)null))
					{
						num4 = 0f;
					}
					else
					{
						Rect rect = component4.rect;
						num4 = ((Rect)(ref rect)).width;
					}
					num3 = num4;
				}
				if (num3 <= 0f)
				{
					num3 = 40f;
				}
				if (num2 > 0)
				{
					num += ((HorizontalOrVerticalLayoutGroup)component2).spacing;
				}
				num += num3;
				num2++;
			}
			num = Mathf.Max(num, 1f);
			component.SetSizeWithCurrentAnchors((Axis)0, num);
			component.SetSizeWithCurrentAnchors((Axis)1, 52f);
			LayoutElement component5 = row.GetComponent<LayoutElement>();
			if ((Object)(object)component5 != (Object)null)
			{
				component5.minWidth = num;
				component5.preferredWidth = num;
			}
		}

		private static Transform GetPromptParent(Indicator indicator)
		{
			Transform val = (((Object)(object)indicator != (Object)null && (Object)(object)indicator.ControlPromptUI != (Object)null) ? indicator.ControlPromptUI.transform : (((Object)(object)indicator != (Object)null) ? ((Component)indicator).transform : null));
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Canvas val2 = ((Component)val).GetComponent<Canvas>() ?? ((Component)val).GetComponentInParent<Canvas>();
			if (!((Object)(object)val2 != (Object)null))
			{
				if (!((Object)(object)val.parent != (Object)null))
				{
					return val;
				}
				return val.parent;
			}
			return ((Component)val2).transform;
		}

		private static void AddVanillaPromptBackground(GameObject row, Indicator indicator)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			Image val = (((Object)(object)indicator != (Object)null && (Object)(object)indicator.BG != (Object)null) ? (((Component)indicator.BG).GetComponent<Image>() ?? ((Component)indicator.BG).GetComponentInChildren<Image>(true)) : null);
			Image val2 = row.GetComponent<Image>() ?? row.AddComponent<Image>();
			((Behaviour)val2).enabled = true;
			((Graphic)val2).raycastTarget = false;
			val2.sprite = (((Object)(object)val != (Object)null) ? val.sprite : null);
			val2.type = (Type)(((Object)(object)val != (Object)null) ? ((int)val.type) : 0);
			if ((Object)(object)val2.sprite == (Object)null)
			{
				val2.sprite = Sprite.Create(Texture2D.whiteTexture, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f));
				val2.type = (Type)0;
			}
			((Graphic)val2).color = new Color(0f, 0f, 0f, 0.88f);
			((Graphic)val2).canvasRenderer.SetColor(((Graphic)val2).color);
			for (int i = 0; i < row.transform.childCount; i++)
			{
				Transform child = row.transform.GetChild(i);
				if (((Object)child).name.IndexOf("VanillaPromptBackground", StringComparison.Ordinal) >= 0)
				{
					((Component)child).gameObject.SetActive(false);
				}
			}
		}

		private void RefreshPromptGlyph(bool controller)
		{
			if ((Object)(object)_undoControlPrompt == (Object)null)
			{
				return;
			}
			if (controller)
			{
				_undoControlPrompt.IgnoreControllerChange = false;
				_undoControlPrompt.Category = 1;
				_undoControlPrompt.Action = 43;
				_undoControlPrompt.ForceUpdate();
				return;
			}
			_undoControlPrompt.IgnoreControllerChange = true;
			object? obj = AccessTools.Field(typeof(MMControlPrompt), "_text")?.GetValue(_undoControlPrompt);
			TMP_Text val = (TMP_Text)((obj is TMP_Text) ? obj : null);
			object? obj2 = AccessTools.Field(typeof(MMControlPrompt), "_iconText")?.GetValue(_undoControlPrompt);
			TMP_Text val2 = (TMP_Text)((obj2 is TMP_Text) ? obj2 : null);
			object? obj3 = AccessTools.Field(typeof(MMControlPrompt), "_icon")?.GetValue(_undoControlPrompt);
			Image val3 = (Image)((obj3 is Image) ? obj3 : null);
			if ((Object)(object)val != (Object)null)
			{
				val.text = (UndoBuildActionConfig.RequireControl.Value ? ("Ctrl+" + ((object)Unsafe.As<KeyCode, KeyCode>(ref _undoKey)/*cast due to .constrained prefix*/).ToString()) : ((object)Unsafe.As<KeyCode, KeyCode>(ref _undoKey)/*cast due to .constrained prefix*/).ToString());
				val.fontSize = 20f;
				val.enableAutoSizing = true;
				val.fontSizeMin = 8f;
				val.fontSizeMax = 20f;
				((Component)val).gameObject.SetActive(true);
			}
			if ((Object)(object)val2 != (Object)null)
			{
				((Component)val2).gameObject.SetActive(false);
			}
			if ((Object)(object)val3 != (Object)null)
			{
				((Component)val3).gameObject.SetActive(true);
			}
		}

		private void HideUndoPrompt()
		{
			if ((Object)(object)_undoPromptCellObject != (Object)null)
			{
				_undoPromptCellObject.SetActive(false);
			}
			RefreshPromptRowVisibility(_promptRowObject);
		}

		private static void RefreshPromptRowVisibility(GameObject row)
		{
			if ((Object)(object)row == (Object)null)
			{
				return;
			}
			bool active = false;
			for (int i = 0; i < row.transform.childCount; i++)
			{
				GameObject gameObject = ((Component)row.transform.GetChild(i)).gameObject;
				if (gameObject.activeSelf && ((Object)gameObject).name.IndexOf("VanillaPromptBackground", StringComparison.Ordinal) < 0)
				{
					active = true;
					break;
				}
			}
			SizePromptRow(row);
			row.SetActive(active);
		}

		private void DestroyUndoPrompt()
		{
			if ((Object)(object)_undoPromptCellObject != (Object)null)
			{
				Object.Destroy((Object)(object)_undoPromptCellObject);
			}
			else
			{
				if ((Object)(object)_undoPromptObject != (Object)null)
				{
					Object.Destroy((Object)(object)_undoPromptObject);
				}
				if ((Object)(object)_undoPromptTextObject != (Object)null)
				{
					Object.Destroy((Object)(object)_undoPromptTextObject);
				}
			}
			_undoPromptCellObject = null;
			_undoPromptObject = null;
			_undoPromptTextObject = null;
			_undoControlPrompt = null;
			_undoPromptText = null;
			_promptWasController = null;
		}

		private static KeyCode ParseKey(string raw, KeyCode fallback)
		{
			//IL_0011: 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_001a: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return (KeyCode)Enum.Parse(typeof(KeyCode), raw, ignoreCase: true);
			}
			catch
			{
				return fallback;
			}
		}
	}
	internal static class UndoBuildActionConfig
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<string> UndoKey;

		internal static ConfigEntry<bool> RequireControl;

		internal static ConfigEntry<bool> EnableControllerUndo;

		internal static ConfigEntry<bool> ShowUndoPrompt;

		internal static ConfigEntry<int> UndoDepth;

		internal static ConfigEntry<bool> AllowCriticalStructures;

		internal static void Bind(ConfigFile config)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			Enabled = config.Bind<bool>("General", "Enabled", true, "Enable Undo Build Action.");
			UndoKey = config.Bind<string>("Controls", "UndoKey", "Z", "KeyCode used for undo.");
			RequireControl = config.Bind<bool>("Controls", "RequireControl", true, "Require Ctrl plus UndoKey.");
			EnableControllerUndo = config.Bind<bool>("Controls", "EnableControllerUndo", true, "Allow the UI Page Left controller action (normally LB/L1) to undo during build placement.");
			ShowUndoPrompt = config.Bind<bool>("UI", "ShowUndoPrompt", true, "Show a vanilla bottom-bar Undo prompt while build placement has an action available to undo.");
			UndoDepth = config.Bind<int>("Undo", "UndoDepth", 10, new ConfigDescription("How many recent placements are kept.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 50), Array.Empty<object>()));
			if (UndoDepth.Value < 10)
			{
				UndoDepth.Value = 10;
			}
			AllowCriticalStructures = config.Bind<bool>("Safety", "AllowCriticalStructures", false, "Allow undo removal of temple/shrine/altar/builder style critical structures.");
		}
	}
	[HarmonyPatch(typeof(Interaction_PlacementRegion), "OnInteract")]
	internal static class InteractionPlacementRegionOnInteractPatch
	{
		private static void Prefix()
		{
			UndoBuildActionPlugin.Instance?.ClearSession();
		}
	}
	[HarmonyPatch(typeof(StructureManager), "AddStructure")]
	internal static class StructureManagerAddStructurePatch
	{
		private static void Postfix(StructureBrain __result)
		{
			UndoBuildActionPlugin.Instance?.RecordLatest(__result);
		}
	}
}

plugins/BetterBuilderTools/UpgradeBuildTools.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Lamb.UI;
using MMTools;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using src.UINavigator;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Upgrade Build Tools")]
[assembly: AssemblyProduct("Upgrade Build Tools")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace UpgradeBuildTools
{
	[BepInPlugin("com.cotl.betterbuildertools.upgradebuildtools", "Upgrade Build Tools", "0.1.1")]
	public sealed class UpgradeBuildToolsPlugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(PlacementRegion), "Upgrade")]
		private static class PlacementRegionUpgradePatch
		{
			private static bool Prefix(PlacementRegion __instance)
			{
				if ((Object)(object)Instance == (Object)null)
				{
					return true;
				}
				if (Instance.ShouldSkipNativeUpgrade(__instance))
				{
					return false;
				}
				Instance.ObserveNativeUpgrade(__instance);
				return true;
			}
		}

		public const string PluginGuid = "com.cotl.betterbuildertools.upgradebuildtools";

		public const string PluginName = "Upgrade Build Tools";

		public const string PluginVersion = "0.1.1";

		private static readonly FieldInfo CurrentUpgradeField = AccessTools.Field(typeof(PlacementRegion), "CurrentStructureToUpgrade");

		private static readonly FieldInfo PlacementObjectField = AccessTools.Field(typeof(PlacementRegion), "placementObject");

		private static readonly FieldInfo PlacementUiField = AccessTools.Field(typeof(PlacementRegion), "placementUI");

		private static readonly FieldInfo TilesField = AccessTools.Field(typeof(PlacementRegion), "Tiles");

		private static readonly FieldInfo TilesInitiatedField = AccessTools.Field(typeof(PlacementRegion), "tilesInitiated");

		private static readonly FieldInfo InputDelayField = AccessTools.Field(typeof(PlacementRegion), "InputDelay");

		private static readonly MethodInfo ClearPrefabsMethod = AccessTools.Method(typeof(PlacementRegion), "ClearPrefabs", (Type[])null, (Type[])null);

		private static readonly MethodInfo UpgradeMethod = AccessTools.Method(typeof(PlacementRegion), "Upgrade", (Type[])null, (Type[])null);

		private static readonly MethodInfo GetMousePositionWorldMethod = AccessTools.Method(typeof(PlacementRegion), "GetMousePositionWorld", (Type[])null, (Type[])null);

		private Harmony _harmony;

		private KeyCode _upgradeAllKey;

		private KeyCode _controllerUpgradeAllKey;

		private Coroutine _batchRoutine;

		private float _lastHeldUpgradeTime;

		private int _suppressNativeUpgradeUntilFrame = -1;

		private bool _invokingCustomUpgrade;

		private PlacementRegion _activeRegion;

		private bool _awaitingMouseRelease;

		private readonly HashSet<int> _handledWhileHeld = new HashSet<int>();

		private Indicator _promptOwner;

		private GameObject _promptRowObject;

		private GameObject _promptCellObject;

		private GameObject _promptObject;

		private MMControlPrompt _promptControl;

		private TMP_Text _promptText;

		private bool? _promptWasController;

		private bool _promptCreationWarningLogged;

		internal static ManualLogSource Log { get; private set; }

		internal static UpgradeBuildToolsPlugin Instance { get; private set; }

		private void Awake()
		{
			//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_0043: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			UpgradeBuildToolsConfig.Bind(((BaseUnityPlugin)this).Config);
			_upgradeAllKey = ParseKey(UpgradeBuildToolsConfig.UpgradeAllKey.Value, (KeyCode)103);
			_controllerUpgradeAllKey = ParseKey(UpgradeBuildToolsConfig.ControllerUpgradeAllKey.Value, (KeyCode)333);
			_harmony = new Harmony("com.cotl.betterbuildertools.upgradebuildtools");
			_harmony.PatchAll(typeof(UpgradeBuildToolsPlugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Upgrade Build Tools 0.1.1 loaded.");
		}

		private void OnDestroy()
		{
			if (_batchRoutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_batchRoutine);
				_batchRoutine = null;
			}
			DestroyPromptUi();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			Instance = null;
		}

		private void Update()
		{
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			if (!UpgradeBuildToolsConfig.Enabled.Value)
			{
				ResetPlacementState(null);
				return;
			}
			PlacementRegion instance = PlacementRegion.Instance;
			if (!IsUpgradePlacement(instance, out var info))
			{
				ResetPlacementState(instance);
				return;
			}
			if ((Object)(object)_activeRegion != (Object)(object)instance)
			{
				_activeRegion = instance;
				_handledWhileHeld.Clear();
				_lastHeldUpgradeTime = 0f;
				_awaitingMouseRelease = true;
			}
			if (_awaitingMouseRelease)
			{
				if (Input.GetMouseButton(0))
				{
					return;
				}
				_awaitingMouseRelease = false;
			}
			if (_batchRoutine == null && UpgradeAllPressed())
			{
				_batchRoutine = ((MonoBehaviour)this).StartCoroutine(UpgradeAllRoutine(instance, info));
			}
			if (_batchRoutine != null || !UpgradeBuildToolsConfig.EnableHoldToUpgrade.Value)
			{
				return;
			}
			if (!IsPlaceHeld())
			{
				_handledWhileHeld.Clear();
			}
			else
			{
				if (!Input.GetMouseButton(0))
				{
					return;
				}
				bool mouseButtonDown = Input.GetMouseButtonDown(0);
				if (mouseButtonDown || !(Time.unscaledTime - _lastHeldUpgradeTime < UpgradeBuildToolsConfig.UpgradeInterval.Value))
				{
					Structure val = FindCursorUpgradeTarget(instance, info.UpgradeFromType);
					if (!((Object)(object)val == (Object)null) && val.Brain != null && val.Brain.Data != null && !_handledWhileHeld.Contains(val.Brain.Data.ID) && TryUpgradeTarget(instance, val, mouseButtonDown))
					{
						_handledWhileHeld.Add(val.Brain.Data.ID);
						_lastHeldUpgradeTime = Time.unscaledTime;
					}
				}
			}
		}

		private void LateUpdate()
		{
			UpdatePrompt();
			if (_suppressNativeUpgradeUntilFrame >= 0 && Time.frameCount > _suppressNativeUpgradeUntilFrame)
			{
				_suppressNativeUpgradeUntilFrame = -1;
			}
		}

		private void ResetPlacementState(PlacementRegion region)
		{
			if (_batchRoutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_batchRoutine);
				_batchRoutine = null;
			}
			_activeRegion = null;
			_awaitingMouseRelease = false;
			_handledWhileHeld.Clear();
			_lastHeldUpgradeTime = 0f;
		}

		private bool UpgradeAllPressed()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(_upgradeAllKey))
			{
				return true;
			}
			if (UpgradeBuildToolsConfig.EnableControllerUpgradeAll.Value)
			{
				return Input.GetKeyDown(_controllerUpgradeAllKey);
			}
			return false;
		}

		private bool IsPlaceHeld()
		{
			if (Input.GetMouseButton(0))
			{
				return true;
			}
			try
			{
				return InputManager.Gameplay.GetPlaceMoveUpgradeButtonHeld(MonoSingleton<UINavigatorNew>.Instance.AllowInputOnlyFromPlayer);
			}
			catch
			{
				return false;
			}
		}

		private static bool IsUpgradePlacement(PlacementRegion region, out StructuresData info)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Invalid comparison between Unknown and I4
			info = null;
			if ((Object)(object)region == (Object)null || (int)region.CurrentMode != 2)
			{
				return false;
			}
			try
			{
				info = StructuresData.GetInfoByType(region.StructureType, 0);
				return info != null && info.IsUpgrade && (int)info.UpgradeFromType > 0;
			}
			catch
			{
				return false;
			}
		}

		private IEnumerator UpgradeAllRoutine(PlacementRegion region, StructuresData upgradeInfo)
		{
			_handledWhileHeld.Clear();
			Structure currentUpgrade = GetCurrentUpgrade(region);
			if ((Object)(object)currentUpgrade != (Object)null && (Object)(object)((Component)currentUpgrade).gameObject != (Object)null && !((Component)currentUpgrade).gameObject.activeSelf)
			{
				((Component)currentUpgrade).gameObject.SetActive(true);
			}
			List<Structure> targets = FindEligibleStructures(region, upgradeInfo.UpgradeFromType);
			if (IsEligibleUpgradeTarget(region, currentUpgrade, upgradeInfo.UpgradeFromType))
			{
				targets.Remove(currentUpgrade);
				targets.Insert(0, currentUpgrade);
			}
			int upgraded = 0;
			if (targets.Count == 0 || !StructuresData.CanAfford(region.StructureType))
			{
				_batchRoutine = null;
				yield break;
			}
			((MonoBehaviour)region).StopAllCoroutines();
			for (int i = 0; i < targets.Count; i++)
			{
				if ((Object)(object)PlacementRegion.Instance != (Object)(object)region)
				{
					break;
				}
				if ((int)region.CurrentMode != 2)
				{
					break;
				}
				Structure target = targets[i];
				if (!IsEligibleUpgradeTarget(region, target, upgradeInfo.UpgradeFromType) || !StructuresData.CanAfford(region.StructureType))
				{
					break;
				}
				if (TryUpgradeTarget(region, target, suppressNativeClick: false))
				{
					upgraded++;
				}
				yield return null;
			}
			if (upgraded > 0)
			{
				Log.LogInfo((object)$"Upgraded {upgraded} {upgradeInfo.UpgradeFromType} structure(s) to {region.StructureType}.");
			}
			_handledWhileHeld.Clear();
			_batchRoutine = null;
			FinishUpgradeBatch(region);
		}

		private static void FinishUpgradeBatch(PlacementRegion region)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Invalid comparison between Unknown and I4
			if ((Object)(object)region == (Object)null)
			{
				Time.timeScale = 1f;
				return;
			}
			((MonoBehaviour)region).StopAllCoroutines();
			try
			{
				DestroyPlacementTiles(region);
				ClearPrefabsMethod?.Invoke(region, null);
				DestroyPrivateObject<PlacementObject>(region, PlacementObjectField);
				DestroyPrivateObject<PlacementObjectUI>(region, PlacementUiField);
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Upgrade batch placement cleanup failed: " + ex.GetBaseException().Message));
			}
			region.CurrentMode = (Mode)0;
			region.StructureType = (TYPES)0;
			region.PlacementPosition = Vector3.zero;
			TilesInitiatedField?.SetValue(region, false);
			GameManager.overridePlayerPosition = false;
			if ((Object)(object)DLCLandController.Instance != (Object)null)
			{
				DLCLandController.Instance.ShowBridge();
			}
			if ((Object)(object)HUD_Manager.Instance != (Object)null)
			{
				HUD_Manager.Instance.Show(1, false);
				HUD_Manager.Instance.ShowEditMode(false);
			}
			if ((Object)(object)WeatherSystemController.Instance != (Object)null)
			{
				WeatherSystemController.Instance.ShowWeather(false, true);
			}
			if ((Object)(object)LightingManager.Instance != (Object)null)
			{
				LightingManager.Instance.inOverride = false;
				LightingManager.Instance.overrideSettings = null;
				LightingManager.Instance.transitionDurationMultiplier = 0.2f;
				LightingManager.Instance.lerpActive = false;
				LightingManager.Instance.UpdateLighting(true, false, false);
				LightingManager.Instance.PrepareLightingSettings(false);
			}
			if ((Object)(object)GameManager.GetInstance() != (Object)null)
			{
				if ((Object)(object)GameManager.GetInstance().CamFollowTarget != (Object)null)
				{
					((Behaviour)GameManager.GetInstance().CamFollowTarget).enabled = true;
				}
				GameManager.GetInstance().RemoveAllFromCamera();
				GameManager.GetInstance().AddPlayerToCamera();
				GameManager.GetInstance().CameraResetTargetZoom();
			}
			if (PlayerFarming.players != null)
			{
				for (int i = 0; i < PlayerFarming.players.Count; i++)
				{
					PlayerFarming val = PlayerFarming.players[i];
					if ((Object)(object)val != (Object)null && (Object)(object)val.state != (Object)null && (int)val.state.CURRENT_STATE == 13)
					{
						val.state.CURRENT_STATE = (State)0;
					}
				}
			}
			if ((Object)(object)AudioManager.Instance != (Object)null)
			{
				AudioManager.Instance.SetBuildSnapshotEnabled(false);
			}
			Time.timeScale = 1f;
			if ((Object)(object)MonoSingleton<UIManager>.Instance != (Object)null && (Object)(object)MonoSingleton<UIManager>.Instance.BuildMenuTemplate != (Object)null)
			{
				Time.timeScale = 0f;
				MonoSingleton<UIManager>.Instance.ShowBuildMenu((TYPES)0);
			}
		}

		private static void DestroyPlacementTiles(PlacementRegion region)
		{
			if (!(TilesField?.GetValue(region) is List<PlacementTile> list))
			{
				return;
			}
			PlacementTile[] array = list.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)array[i]).gameObject);
				}
			}
			list.Clear();
		}

		private static void DestroyPrivateObject<T>(PlacementRegion region, FieldInfo field) where T : Component
		{
			object? obj = field?.GetValue(region);
			T val = (T)((obj is T) ? obj : null);
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val).gameObject);
				field.SetValue(region, null);
			}
		}

		private bool TryUpgradeTarget(PlacementRegion region, Structure target, bool suppressNativeClick)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			if (UpgradeMethod == null || CurrentUpgradeField == null || PlacementObjectField == null || (Object)(object)target == (Object)null || target.Brain == null || target.Brain.Data == null)
			{
				Log.LogWarning((object)"Native upgrade members were not found; upgrade tools are unavailable for this game build.");
				return false;
			}
			StructuresData infoByType = StructuresData.GetInfoByType(region.StructureType, 0);
			if (infoByType == null || !IsEligibleUpgradeTarget(region, target, infoByType.UpgradeFromType) || !StructuresData.CanAfford(region.StructureType))
			{
				return false;
			}
			Structure currentUpgrade = GetCurrentUpgrade(region);
			if ((Object)(object)currentUpgrade != (Object)null && (Object)(object)currentUpgrade != (Object)(object)target && (Object)(object)((Component)currentUpgrade).gameObject != (Object)null && !((Component)currentUpgrade).gameObject.activeSelf && !_handledWhileHeld.Contains(GetStructureId(currentUpgrade)))
			{
				((Component)currentUpgrade).gameObject.SetActive(true);
			}
			CurrentUpgradeField.SetValue(region, target);
			((Component)target).gameObject.SetActive(false);
			if (InputDelayField != null)
			{
				InputDelayField.SetValue(region, 0.2f);
			}
			if (suppressNativeClick)
			{
				_suppressNativeUpgradeUntilFrame = Time.frameCount + 1;
			}
			try
			{
				_invokingCustomUpgrade = true;
				UpgradeMethod.Invoke(region, null);
				_invokingCustomUpgrade = false;
				return true;
			}
			catch (Exception ex)
			{
				_invokingCustomUpgrade = false;
				if ((Object)(object)((Component)target).gameObject != (Object)null)
				{
					((Component)target).gameObject.SetActive(true);
				}
				Log.LogWarning((object)("Upgrade action failed: " + ex.GetBaseException().Message));
				return false;
			}
		}

		private Structure FindCursorUpgradeTarget(PlacementRegion region, TYPES fromType)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_0047: 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)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			if (GetMousePositionWorldMethod == null)
			{
				return null;
			}
			Vector3 val;
			try
			{
				val = (Vector3)GetMousePositionWorldMethod.Invoke(region, null);
			}
			catch
			{
				return null;
			}
			PlacementTile closestTileAtWorldPosition = region.GetClosestTileAtWorldPosition(val, -1f);
			if ((Object)(object)closestTileAtWorldPosition == (Object)null)
			{
				return null;
			}
			TileGridTile tileGridTile = region.GetTileGridTile(closestTileAtWorldPosition.GridPosition);
			if (tileGridTile != null && tileGridTile.ObjectID >= 0)
			{
				Structure val2 = FindStructureById(tileGridTile.ObjectID);
				if (IsEligibleUpgradeTarget(region, val2, fromType))
				{
					return val2;
				}
			}
			Structure[] array = Structure.Structures.ToArray();
			foreach (Structure val3 in array)
			{
				if (IsEligibleUpgradeTarget(region, val3, fromType))
				{
					Vector2Int gridTilePosition = val3.Brain.Data.GridTilePosition;
					Vector2Int bounds = val3.Brain.Data.Bounds;
					if (((Vector2Int)(ref closestTileAtWorldPosition.GridPosition)).x >= ((Vector2Int)(ref gridTilePosition)).x && ((Vector2Int)(ref closestTileAtWorldPosition.GridPosition)).x < ((Vector2Int)(ref gridTilePosition)).x + ((Vector2Int)(ref bounds)).x && ((Vector2Int)(ref closestTileAtWorldPosition.GridPosition)).y >= ((Vector2Int)(ref gridTilePosition)).y && ((Vector2Int)(ref closestTileAtWorldPosition.GridPosition)).y < ((Vector2Int)(ref gridTilePosition)).y + ((Vector2Int)(ref bounds)).y)
					{
						return val3;
					}
				}
			}
			return null;
		}

		private static List<Structure> FindEligibleStructures(PlacementRegion region, TYPES fromType)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			List<Structure> list = new List<Structure>();
			Structure[] array = Structure.Structures.ToArray();
			foreach (Structure val in array)
			{
				if (IsEligibleUpgradeTarget(region, val, fromType))
				{
					list.Add(val);
				}
			}
			return list;
		}

		private static bool IsEligibleUpgradeTarget(PlacementRegion region, Structure target, TYPES fromType)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Invalid comparison between Unknown and I4
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_007c: Invalid comparison between Unknown and I4
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Invalid comparison between Unknown and I4
			if ((Object)(object)target == (Object)null || !((Component)target).gameObject.activeInHierarchy || target.Brain == null || target.Brain.Data == null || target.Type != fromType)
			{
				return false;
			}
			if ((Object)(object)region != (Object)null && region.StructureInfo != null && target.Structure_Info.Location != region.StructureInfo.Location)
			{
				return false;
			}
			TYPES type = target.Type;
			if (target.Structure_Info.ClaimedByPlayer && ((int)type == 2 || (int)type == 40 || (int)type == 41))
			{
				return false;
			}
			return true;
		}

		private static Structure FindStructureById(int id)
		{
			Structure[] array = Structure.Structures.ToArray();
			foreach (Structure val in array)
			{
				if ((Object)(object)val != (Object)null && val.Brain != null && val.Brain.Data != null && val.Brain.Data.ID == id)
				{
					return val;
				}
			}
			return null;
		}

		private static Structure GetCurrentUpgrade(PlacementRegion region)
		{
			object? obj = CurrentUpgradeField?.GetValue(region);
			return (Structure)((obj is Structure) ? obj : null);
		}

		private static int GetStructureId(Structure structure)
		{
			if (!((Object)(object)structure != (Object)null) || structure.Brain == null || structure.Brain.Data == null)
			{
				return -1;
			}
			return structure.Brain.Data.ID;
		}

		internal void ObserveNativeUpgrade(PlacementRegion region)
		{
			if (!_invokingCustomUpgrade && !((Object)(object)region == (Object)null) && IsPlaceHeld())
			{
				int structureId = GetStructureId(GetCurrentUpgrade(region));
				if (structureId >= 0)
				{
					_handledWhileHeld.Add(structureId);
				}
			}
		}

		internal bool ShouldSkipNativeUpgrade(PlacementRegion region)
		{
			if (_invokingCustomUpgrade || (Object)(object)region == (Object)null || _suppressNativeUpgradeUntilFrame < Time.frameCount)
			{
				return false;
			}
			_suppressNativeUpgradeUntilFrame = -1;
			return true;
		}

		private void UpdatePrompt()
		{
			if (!UpgradeBuildToolsConfig.ShowUpgradeAllPrompt.Value || !UpgradeBuildToolsConfig.Enabled.Value || (Object)(object)PlayerFarming.Instance == (Object)null || (Object)(object)PlayerFarming.Instance.indicator == (Object)null)
			{
				HidePrompt();
				return;
			}
			if (!IsUpgradePlacement(PlacementRegion.Instance, out var _))
			{
				HidePrompt();
				return;
			}
			Indicator indicator = PlayerFarming.Instance.indicator;
			if (EnsurePrompt(indicator))
			{
				bool flag = IsControllerInput();
				_promptControl.playerFarming = PlayerFarming.Instance;
				_promptControl.PrioritizeMouse = false;
				_promptText.text = "Upgrade all";
				_promptCellObject.SetActive(true);
				SizePromptRow(_promptRowObject);
				_promptRowObject.SetActive(true);
				if (_promptWasController != flag)
				{
					_promptWasController = flag;
					RefreshPromptGlyph(flag);
				}
			}
		}

		private bool EnsurePrompt(Indicator indicator)
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_promptOwner == (Object)(object)indicator && (Object)(object)_promptCellObject != (Object)null && (Object)(object)_promptControl != (Object)null && (Object)(object)_promptText != (Object)null)
			{
				return true;
			}
			DestroyPromptUi();
			if ((Object)(object)indicator == (Object)null || (Object)(object)indicator.FourthControlPrompt == (Object)null || (Object)(object)((Transform)indicator.FourthControlPrompt).parent == (Object)null || (Object)(object)indicator.Fourthtext == (Object)null)
			{
				return false;
			}
			EnsurePromptRow(indicator);
			if ((Object)(object)_promptRowObject == (Object)null)
			{
				return false;
			}
			GameObject val = new GameObject("UpgradeBuildTools_UpgradeAllCell");
			((Transform)val.AddComponent<RectTransform>()).SetParent(_promptRowObject.transform, false);
			LayoutElement obj = val.AddComponent<LayoutElement>();
			obj.preferredWidth = 150f;
			obj.minWidth = 150f;
			HorizontalLayoutGroup obj2 = val.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)obj2).spacing = 6f;
			((LayoutGroup)obj2).childAlignment = (TextAnchor)4;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = true;
			GameObject val2 = Object.Instantiate<GameObject>(((Component)indicator.FourthControlPrompt).gameObject, val.transform, false);
			((Object)val2).name = "UpgradeBuildTools_UpgradeAllKey";
			val2.SetActive(true);
			val2.transform.localScale = Vector3.one;
			MMControlPrompt val3 = val2.GetComponent<MMControlPrompt>() ?? val2.GetComponentInChildren<MMControlPrompt>(true);
			LayoutElement obj3 = val2.GetComponent<LayoutElement>() ?? val2.AddComponent<LayoutElement>();
			obj3.preferredWidth = 50f;
			obj3.minWidth = 42f;
			obj3.preferredHeight = 40f;
			TMP_Text val4 = (TMP_Text)(object)Object.Instantiate<TextMeshProUGUI>(indicator.Fourthtext, val.transform, false);
			((Object)val4).name = "UpgradeBuildTools_UpgradeAllLabel";
			((Component)val4).gameObject.SetActive(true);
			val4.transform.localScale = Vector3.one;
			val4.alignment = (TextAlignmentOptions)4097;
			val4.enableAutoSizing = true;
			val4.fontSizeMin = 12f;
			val4.fontSizeMax = 22f;
			LayoutElement obj4 = ((Component)val4).GetComponent<LayoutElement>() ?? ((Component)val4).gameObject.AddComponent<LayoutElement>();
			obj4.preferredWidth = 92f;
			obj4.minWidth = 92f;
			Behaviour[] components = ((Component)val4).GetComponents<Behaviour>();
			foreach (Behaviour val5 in components)
			{
				if ((Object)(object)val5 != (Object)null && ((object)val5).GetType().FullName == "I2.Loc.Localize")
				{
					val5.enabled = false;
				}
			}
			if ((Object)(object)val3 == (Object)null)
			{
				Object.Destroy((Object)(object)val);
				if (!_promptCreationWarningLogged)
				{
					_promptCreationWarningLogged = true;
					Log.LogWarning((object)"Could not create the standalone Upgrade All control prompt.");
				}
				return false;
			}
			_promptOwner = indicator;
			_promptCellObject = val;
			_promptObject = val2;
			_promptControl = val3;
			_promptText = val4;
			_promptWasController = null;
			_promptCreationWarningLogged = false;
			return true;
		}

		private void EnsurePromptRow(Indicator indicator)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			Transform promptParent = GetPromptParent(indicator);
			if (!((Object)(object)promptParent == (Object)null))
			{
				Transform val = promptParent.Find("RemoteBuildCancel_BuilderToolsPromptRow");
				if ((Object)(object)val != (Object)null)
				{
					ConfigurePromptRow(((Component)val).gameObject);
					AddVanillaPromptBackground(((Component)val).gameObject, indicator);
					_promptOwner = indicator;
					_promptRowObject = ((Component)val).gameObject;
				}
				else
				{
					GameObject val2 = new GameObject("RemoteBuildCancel_BuilderToolsPromptRow");
					((Transform)val2.AddComponent<RectTransform>()).SetParent(promptParent, false);
					ConfigurePromptRow(val2);
					AddVanillaPromptBackground(val2, indicator);
					val2.transform.SetAsLastSibling();
					_promptOwner = indicator;
					_promptRowObject = val2;
				}
			}
		}

		private static void ConfigurePromptRow(GameObject row)
		{
			//IL_001b: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Expected O, but got Unknown
			RectTransform obj = row.GetComponent<RectTransform>() ?? row.AddComponent<RectTransform>();
			obj.anchorMin = new Vector2(0.5f, 0f);
			obj.anchorMax = new Vector2(0.5f, 0f);
			obj.pivot = new Vector2(0f, 0f);
			obj.anchoredPosition = new Vector2(240f, 112f);
			obj.sizeDelta = new Vector2(0f, 52f);
			LayoutElement obj2 = row.GetComponent<LayoutElement>() ?? row.AddComponent<LayoutElement>();
			obj2.minWidth = 0f;
			obj2.preferredWidth = 0f;
			obj2.flexibleWidth = 0f;
			obj2.minHeight = 52f;
			obj2.preferredHeight = 52f;
			obj2.flexibleHeight = 0f;
			ContentSizeFitter obj3 = row.GetComponent<ContentSizeFitter>() ?? row.AddComponent<ContentSizeFitter>();
			obj3.horizontalFit = (FitMode)2;
			obj3.verticalFit = (FitMode)0;
			((Behaviour)obj3).enabled = false;
			HorizontalLayoutGroup obj4 = row.GetComponent<HorizontalLayoutGroup>() ?? row.AddComponent<HorizontalLayoutGroup>();
			((LayoutGroup)obj4).padding = new RectOffset(18, 18, 5, 5);
			((HorizontalOrVerticalLayoutGroup)obj4).spacing = 18f;
			((LayoutGroup)obj4).childAlignment = (TextAnchor)4;
			((HorizontalOrVerticalLayoutGroup)obj4).childControlWidth = true;
			((HorizontalOrVerticalLayoutGroup)obj4).childControlHeight = true;
			((HorizontalOrVerticalLayoutGroup)obj4).childForceExpandWidth = false;
			((HorizontalOrVerticalLayoutGroup)obj4).childForceExpandHeight = true;
		}

		private static void SizePromptRow(GameObject row)
		{
			if ((Object)(object)row == (Object)null)
			{
				return;
			}
			RectTransform component = row.GetComponent<RectTransform>();
			HorizontalLayoutGroup component2 = row.GetComponent<HorizontalLayoutGroup>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
			{
				return;
			}
			float num = ((LayoutGroup)component2).padding.left + ((LayoutGroup)component2).padding.right;
			int num2 = 0;
			for (int i = 0; i < row.transform.childCount; i++)
			{
				GameObject gameObject = ((Component)row.transform.GetChild(i)).gameObject;
				if (gameObject.activeSelf && ((Object)gameObject).name.IndexOf("VanillaPromptBackground", StringComparison.Ordinal) < 0)
				{
					LayoutElement component3 = gameObject.GetComponent<LayoutElement>();
					float num3 = (((Object)(object)component3 != (Object)null) ? Mathf.Max(component3.minWidth, component3.preferredWidth) : 0f);
					if (num3 <= 0f)
					{
						num3 = 40f;
					}
					if (num2 > 0)
					{
						num += ((HorizontalOrVerticalLayoutGroup)component2).spacing;
					}
					num += num3;
					num2++;
				}
			}
			num = Mathf.Max(num, 1f);
			component.SetSizeWithCurrentAnchors((Axis)0, num);
			component.SetSizeWithCurrentAnchors((Axis)1, 52f);
			LayoutElement component4 = row.GetComponent<LayoutElement>();
			if ((Object)(object)component4 != (Object)null)
			{
				component4.minWidth = num;
				component4.preferredWidth = num;
			}
		}

		private static Transform GetPromptParent(Indicator indicator)
		{
			Transform val = (((Object)(object)indicator != (Object)null && (Object)(object)indicator.ControlPromptUI != (Object)null) ? indicator.ControlPromptUI.transform : (((Object)(object)indicator != (Object)null) ? ((Component)indicator).transform : null));
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Canvas val2 = ((Component)val).GetComponent<Canvas>() ?? ((Component)val).GetComponentInParent<Canvas>();
			if (!((Object)(object)val2 != (Object)null))
			{
				if (!((Object)(object)val.parent != (Object)null))
				{
					return val;
				}
				return val.parent;
			}
			return ((Component)val2).transform;
		}

		private static void AddVanillaPromptBackground(GameObject row, Indicator indicator)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			Image val = (((Object)(object)indicator != (Object)null && (Object)(object)indicator.BG != (Object)null) ? (((Component)indicator.BG).GetComponent<Image>() ?? ((Component)indicator.BG).GetComponentInChildren<Image>(true)) : null);
			Image val2 = row.GetComponent<Image>() ?? row.AddComponent<Image>();
			((Behaviour)val2).enabled = true;
			((Graphic)val2).raycastTarget = false;
			val2.sprite = (((Object)(object)val != (Object)null) ? val.sprite : null);
			val2.type = (Type)(((Object)(object)val != (Object)null) ? ((int)val.type) : 0);
			if ((Object)(object)val2.sprite == (Object)null)
			{
				val2.sprite = Sprite.Create(Texture2D.whiteTexture, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f));
				val2.type = (Type)0;
			}
			((Graphic)val2).color = new Color(0f, 0f, 0f, 0.88f);
			((Graphic)val2).canvasRenderer.SetColor(((Graphic)val2).color);
		}

		private void RefreshPromptGlyph(bool controller)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_promptControl == (Object)null))
			{
				SetCustomPromptKey(_promptControl, controller ? ControllerButtonLabel(_controllerUpgradeAllKey) : ((object)Unsafe.As<KeyCode, KeyCode>(ref _upgradeAllKey)/*cast due to .constrained prefix*/).ToString());
			}
		}

		private static void SetCustomPromptKey(MMControlPrompt prompt, string label)
		{
			prompt.IgnoreControllerChange = true;
			object? obj = AccessTools.Field(typeof(MMControlPrompt), "_text")?.GetValue(prompt);
			TMP_Text val = (TMP_Text)((obj is TMP_Text) ? obj : null);
			object? obj2 = AccessTools.Field(typeof(MMControlPrompt), "_iconText")?.GetValue(prompt);
			TMP_Text val2 = (TMP_Text)((obj2 is TMP_Text) ? obj2 : null);
			object? obj3 = AccessTools.Field(typeof(MMControlPrompt), "_icon")?.GetValue(prompt);
			Image val3 = (Image)((obj3 is Image) ? obj3 : null);
			if ((Object)(object)val != (Object)null)
			{
				val.text = label;
				val.fontSize = 20f;
				val.enableAutoSizing = true;
				val.fontSizeMin = 8f;
				val.fontSizeMax = 20f;
				((Component)val).gameObject.SetActive(true);
			}
			if ((Object)(object)val2 != (Object)null)
			{
				((Component)val2).gameObject.SetActive(false);
			}
			if ((Object)(object)val3 != (Object)null)
			{
				((Component)val3).gameObject.SetActive(true);
			}
		}

		private static bool IsControllerInput()
		{
			try
			{
				return (Object)(object)PlayerFarming.Instance != (Object)null && InputManager.General.InputIsController(PlayerFarming.Instance);
			}
			catch
			{
				return false;
			}
		}

		private unsafe static string ControllerButtonLabel(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected I4, but got Unknown
			return (key - 330) switch
			{
				0 => "A", 
				1 => "B", 
				2 => "X", 
				3 => "Y", 
				4 => "LB", 
				5 => "RB", 
				6 => "Back", 
				7 => "Start", 
				8 => "LS", 
				9 => "RS", 
				_ => ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString().Replace("JoystickButton", "Pad "), 
			};
		}

		private void HidePrompt()
		{
			if ((Object)(object)_promptCellObject != (Object)null)
			{
				_promptCellObject.SetActive(false);
			}
			RefreshPromptRowVisibility(_promptRowObject);
		}

		private static void RefreshPromptRowVisibility(GameObject row)
		{
			if ((Object)(object)row == (Object)null)
			{
				return;
			}
			bool active = false;
			for (int i = 0; i < row.transform.childCount; i++)
			{
				GameObject gameObject = ((Component)row.transform.GetChild(i)).gameObject;
				if (gameObject.activeSelf && ((Object)gameObject).name.IndexOf("VanillaPromptBackground", StringComparison.Ordinal) < 0)
				{
					active = true;
					break;
				}
			}
			SizePromptRow(row);
			row.SetActive(active);
		}

		private void DestroyPromptUi()
		{
			if ((Object)(object)_promptCellObject != (Object)null)
			{
				Object.Destroy((Object)(object)_promptCellObject);
			}
			_promptOwner = null;
			_promptRowObject = null;
			_promptCellObject = null;
			_promptObject = null;
			_promptControl = null;
			_promptText = null;
			_promptWasController = null;
		}

		private static KeyCode ParseKey(string raw, KeyCode fallback)
		{
			//IL_0011: 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_001a: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return (KeyCode)Enum.Parse(typeof(KeyCode), raw, ignoreCase: true);
			}
			catch
			{
				return fallback;
			}
		}
	}
	internal static class UpgradeBuildToolsConfig
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> EnableHoldToUpgrade;

		internal static ConfigEntry<bool> EnableControllerUpgradeAll;

		internal static ConfigEntry<bool> ShowUpgradeAllPrompt;

		internal static ConfigEntry<string> UpgradeAllKey;

		internal static ConfigEntry<string> ControllerUpgradeAllKey;

		internal static ConfigEntry<float> UpgradeInterval;

		internal static void Bind(ConfigFile config)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			Enabled = config.Bind<bool>("General", "Enabled", true, "Enable Upgrade Build Tools.");
			ShowUpgradeAllPrompt = config.Bind<bool>("General", "ShowUpgradeAllPrompt", true, "Show the vanilla-style Upgrade all prompt while an upgrade is selected.");
			EnableHoldToUpgrade = config.Bind<bool>("Behavior", "EnableHoldToUpgrade", true, "Upgrade each new structure under the mouse while the normal place input is held.");
			UpgradeInterval = config.Bind<float>("Behavior", "UpgradeInterval", 0.16f, new ConfigDescription("Minimum seconds between held upgrades. Matches Path Brush Plus by default.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>()));
			UpgradeAllKey = config.Bind<string>("Controls", "UpgradeAllKey", "G", "Keyboard key that upgrades every eligible previous-tier structure to the selected upgrade.");
			EnableControllerUpgradeAll = config.Bind<bool>("Controls", "EnableControllerUpgradeAll", true, "Enable the controller shortcut for Upgrade all.");
			ControllerUpgradeAllKey = config.Bind<string>("Controls", "ControllerUpgradeAllKey", "JoystickButton3", "Controller button used for Upgrade all. JoystickButton3 is Y on the standard layout.");
		}
	}
}