Decompiled source of Thorn v0.1.1

plugins\ThornClient.dll

Decompiled 6 hours ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using Notiffy.API;
using NukeLib.Game;
using NukeLib.UI;
using NukeLib.Utils;
using TMPro;
using ThornClient.Core;
using ThornClient.Core.ConfigurableElements;
using ThornClient.Core.DataTypes;
using ThornClient.HUD;
using ThornClient.HUD.HUDComponents;
using ThornClient.Managers;
using ThornClient.Modules.Utility;
using ThornClient.Patches;
using ThornClient.System;
using ThornClient.System.ClickGUIComponents;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ThornClient")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+db84fde6ff0fea005b6ecad8063809958db7c7f9")]
[assembly: AssemblyProduct("ThornClient")]
[assembly: AssemblyTitle("ThornClient")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 ThornClient
{
	[BepInPlugin("com.github.end-4.thornClient", "Thorn", "0.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		public static string workingPath = Assembly.GetExecutingAssembly().Location;

		public static string workingDir = Path.GetDirectoryName(workingPath);

		public const string PluginGUID = "com.github.end-4.thornClient";

		public const string PluginName = "Thorn";

		public const string PluginVersion = "0.1.0";

		public static string PluginIconPath = Path.Combine(workingDir, "icon.png");

		public static Plugin Instance { get; private set; }

		private void Awake()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			if (!((Object)(object)Instance != (Object)null))
			{
				Instance = this;
				AssetManager.Initialize();
				HudManager.Initialize();
				EffectManager.Initialize();
				ModuleManager.Initialize();
				RenderManager.Initialize();
				ConfigManager.LoadAll();
				ConfigManager.SetupFileWatcher();
				new Harmony("com.github.end-4.thornClient").PatchAll(typeof(OptionsManagerPatches));
				Log.LogInfo((object)"Thorn is loaded");
			}
		}

		private void Update()
		{
			ConfigManager.UpdateMainThreadQueue();
			InputManager.Update();
			foreach (ThornClient.Core.Module item in ModuleManager.Items)
			{
				if (item.IsEnabled)
				{
					try
					{
						item.OnUpdate();
					}
					catch (Exception ex)
					{
						NotificationSystem.NotifySend("Thorn > " + item.Name, "Error in update loop of " + item.Name + ", disabling to prevent further issues. Check the logs for further details.", (Sprite)null, PluginIconPath, (Urgency)1, "Thorn", 0u, (Dictionary<string, string>)null, -1);
						Log.LogError((object)("Error in module '" + item.Name + "' during Update! Disabling to prevent log spam/crashes"));
						Log.LogError((object)ex);
						item.Toggle();
					}
				}
			}
		}

		private void OnRenderObject()
		{
			RenderManager.RenderPipeline();
		}
	}
}
namespace ThornClient.System
{
	public class ClickGUI : SystemModule
	{
		internal static ClickGUI? Instance;

		private const string PauseGameStateKey = "Thorn_ClickGUI";

		private static readonly string BundlePath = Path.Combine(Plugin.workingDir, "assets", "thorn_clickgui.bundle");

		public static readonly string BundleKey = "clickGui";

		private static GameObject? _layoutedPagePrefab;

		private bool _isInitialized;

		private GameObject? _canvas;

		private GameObject? _tabBar;

		private GameObject? _modulePage;

		private GameObject? _hudPage;

		private GameObject? _settingsPage;

		private GameObject? _configPopupPage;

		private readonly Stack<GameObject> _panelStack = new Stack<GameObject>();

		private GameObject? _tooltip;

		private GameObject? _tabBarButtonRow;

		private ModuleSearchWindowController? _moduleSearchController;

		private ModuleSearchWindowController? _hudModuleSearchController;

		private List<Tuple<string, GameObject>> _tabPages = new List<Tuple<string, GameObject>>();

		private const string ModuleTabName = "Modules";

		private const string HudTabName = "HUD";

		private static readonly Vector2 PageHiddenOffset = Vector2.down * 15f;

		private static string _lastTabName = "";

		private static OptionsManager? opts => MonoSingleton<OptionsManager>.Instance;

		public ClickGUI()
			: base("thorn.clickGui", "ClickGUI", "The main interaction panel")
		{
			AssetManager.LoadBundle(BundleKey, BundlePath);
			SceneUtils.SafeSceneLoaded += delegate
			{
				_isInitialized = InitializeIfNeeded();
				if (IsEnabled)
				{
					Toggle();
				}
			};
		}

		private bool InitializeIfNeeded()
		{
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0356: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_0421: Expected O, but got Unknown
			//IL_0429: Unknown result type (might be due to invalid IL or missing references)
			if (Instance != null || (_isInitialized && (Object)(object)_canvas != (Object)null))
			{
				return true;
			}
			Instance = this;
			GameObject val = AssetManager.Get<GameObject>(BundleKey, "ThornClickGUICanvas");
			GameObject val2 = AssetManager.Get<GameObject>(BundleKey, "TabBar");
			_layoutedPagePrefab = AssetManager.Get<GameObject>(BundleKey, "LayoutedPage");
			GameObject val3 = AssetManager.Get<GameObject>(BundleKey, "Tooltip");
			GameObject val4 = AssetManager.Get<GameObject>(BundleKey, "TabButton");
			GameObject val5 = AssetManager.Get<GameObject>(BundleKey, "ModuleCategory");
			GameObject val6 = AssetManager.Get<GameObject>(BundleKey, "SearchWindow");
			_canvas = Object.Instantiate<GameObject>(val);
			((Object)_canvas).hideFlags = (HideFlags)52;
			Object.DontDestroyOnLoad((Object)(object)_canvas);
			_canvas.SetActive(true);
			_tabBar = Object.Instantiate<GameObject>(val2, _canvas.transform);
			_tabBar.SetActive(true);
			GameObjectExtensions.GetOrAddComponent<TabBarController>(_tabBar);
			_modulePage = Object.Instantiate<GameObject>(_layoutedPagePrefab, _canvas.transform);
			_hudPage = Object.Instantiate<GameObject>(_layoutedPagePrefab, _canvas.transform);
			_settingsPage = Object.Instantiate<GameObject>(_layoutedPagePrefab, _canvas.transform);
			_tabPages.Add(Tuple.Create<string, GameObject>("Modules", _modulePage));
			_tabPages.Add(Tuple.Create<string, GameObject>("HUD", _hudPage));
			_tabPages.Add(Tuple.Create<string, GameObject>("Settings", _settingsPage));
			_lastTabName = "Modules";
			for (int i = 0; i < Enum.GetValues(typeof(ModuleCategory)).Length; i++)
			{
				ModuleCategory moduleCategory = (ModuleCategory)i;
				if (moduleCategory != ModuleCategory.Hud)
				{
					GameObject val7 = Object.Instantiate<GameObject>(val5);
					AddToLayoutedPage(_modulePage, val7);
					ModuleCategoryController orAddComponent = GameObjectExtensions.GetOrAddComponent<ModuleCategoryController>(val7);
					orAddComponent.Category = moduleCategory;
					orAddComponent.SetupModules();
					UIUtils.UnfuckLayoutHack(val7);
				}
			}
			GameObject val8 = Object.Instantiate<GameObject>(val6);
			AddToLayoutedPage(_modulePage, val8);
			_moduleSearchController = val8.AddComponent<ModuleSearchWindowController>();
			_moduleSearchController.ModuleFilter = (ThornClient.Core.Module module) => !(module is SystemModule) && !(module is HudModule);
			UIUtils.UnfuckLayoutHack(_modulePage);
			GameObject val9 = Object.Instantiate<GameObject>(val5);
			AddToLayoutedPage(_hudPage, val9);
			ModuleCategoryController orAddComponent2 = GameObjectExtensions.GetOrAddComponent<ModuleCategoryController>(val9);
			orAddComponent2.Category = ModuleCategory.Hud;
			orAddComponent2.SetupModules();
			UIUtils.UnfuckLayoutHack(val9);
			RectTransform val10 = (RectTransform)val9.transform;
			UIUtils.UnfuckLayoutHack(val9);
			val10.pivot = new Vector2(0.5f, 0.5f);
			((Transform)val10).localPosition = new Vector3(0f, 0f, 0f);
			GameObject val11 = Object.Instantiate<GameObject>(val6);
			AddToLayoutedPage(_hudPage, val11);
			_hudModuleSearchController = val11.AddComponent<ModuleSearchWindowController>();
			_hudModuleSearchController.ModuleFilter = (ThornClient.Core.Module module) => module is HudModule;
			UIUtils.UnfuckLayoutHack(_hudPage);
			GameObject val12 = Object.Instantiate<GameObject>(val5);
			AddToLayoutedPage(_settingsPage, val12);
			RectTransform val13 = (RectTransform)val12.transform;
			val13.pivot = new Vector2(0.5f, 0.5f);
			((Transform)val13).localPosition = new Vector3(0f, 0f, 0f);
			GameObjectExtensions.GetOrAddComponent<ConfigurableWindowController>(val12).TargetConfigurable = ThornModule.Instance;
			UIUtils.UnfuckLayoutHack(_settingsPage);
			_tabBarButtonRow = UIUtils.FindRecursive(_tabBar, "Tabs");
			foreach (Tuple<string, GameObject> tabPage in _tabPages)
			{
				string key = tabPage.Item1;
				GameObject obj = Object.Instantiate<GameObject>(val4, _tabBarButtonRow.transform);
				((TMP_Text)UIUtils.FindRecursive(obj, "Text").GetComponent<TextMeshProUGUI>()).text = key;
				((UnityEvent)obj.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
				{
					SetTab(key);
				});
				SlideFadeToggleEffectExtensions.SetActiveAnimated(tabPage.Item2, false, PageHiddenOffset, 25f);
			}
			UIUtils.UnfuckLayoutHack(_tabBarButtonRow);
			_tooltip = Object.Instantiate<GameObject>(val3, _canvas.transform);
			_tooltip.SetActive(false);
			CanvasGroup component = _canvas.GetComponent<CanvasGroup>();
			if ((Object)(object)component != (Object)null)
			{
				component.alpha = 1f;
			}
			SetTab("Modules", animated: false);
			_canvas.SetActive(false);
			return true;
		}

		private static GameObject AddToLayoutedPage(GameObject page, GameObject item)
		{
			GameObject obj = UIUtils.FindRecursive(page, "Layout");
			Transform val = ((obj != null) ? obj.transform : null);
			if ((Object)(object)val == (Object)null || (Object)(object)item == (Object)null)
			{
				return item;
			}
			item.transform.SetParent(val, false);
			UIUtils.UnfuckLayoutHack(((Component)val).gameObject);
			return item;
		}

		protected override void OnEnable()
		{
			if (!((Object)(object)_canvas == (Object)null))
			{
				_canvas.transform.SetAsLastSibling();
				_canvas.SetActive(true);
				Canvas component = _canvas.GetComponent<Canvas>();
				if ((Object)(object)component != (Object)null)
				{
					component.sortingOrder = 69;
				}
				UIUtils.UnfuckLayoutHack(_canvas);
				ThornModule? instance = ThornModule.Instance;
				if (instance == null || instance.MenuPausesGame.Value)
				{
					Pauser.Pause(true, "Thorn_ClickGUI");
				}
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
				PerformInitialFocus();
			}
		}

		protected override void OnDisable()
		{
			if (!((Object)(object)_canvas == (Object)null))
			{
				_canvas.SetActive(false);
				Pauser.Pause(true, "Thorn_ClickGUI");
				Pauser.Pause(false, "Thorn_ClickGUI");
				if ((Object)(object)_tooltip != (Object)null)
				{
					_tooltip.SetActive(false);
				}
			}
		}

		public override void OnUpdate()
		{
			UpdateTooltipPos();
		}

		private void UpdateTooltipPos()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//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_0050: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_tooltip == (Object)null) && _tooltip.activeInHierarchy)
			{
				RectTransform val = (RectTransform)_tooltip.transform;
				((Transform)val).position = Input.mousePosition + new Vector3(70f + val.sizeDelta.x / 2f, -40f - val.sizeDelta.y / 2f, 0f);
				_tooltip.transform.SetAsLastSibling();
			}
		}

		public static string GetTooltipText()
		{
			if (Instance == null || (Object)(object)Instance._tooltip == (Object)null)
			{
				return "";
			}
			GameObject val = UIUtils.FindRecursive(Instance._tooltip, "Text");
			if ((Object)(object)val == (Object)null)
			{
				return "";
			}
			return ((TMP_Text)val.GetComponent<TextMeshProUGUI>()).text;
		}

		public static void SetTooltipText(string text)
		{
			string text2 = TextUtils.WrapText(text, 30);
			if (Instance != null && !((Object)(object)Instance._tooltip == (Object)null))
			{
				GameObject val = UIUtils.FindRecursive(Instance._tooltip, "Text");
				if (!((Object)(object)val == (Object)null))
				{
					((TMP_Text)val.GetComponent<TextMeshProUGUI>()).text = text2;
					Instance._tooltip.SetActive(true);
					UIUtils.UnfuckLayoutHack(Instance._tooltip);
					Instance.UpdateTooltipPos();
				}
			}
		}

		public static void SurrenderTooltipText(string text, bool force = false)
		{
			string text2 = TextUtils.WrapText(text, 30);
			if (Instance == null || (Object)(object)Instance._tooltip == (Object)null)
			{
				return;
			}
			GameObject val = UIUtils.FindRecursive(Instance._tooltip, "Text");
			if (!((Object)(object)val == (Object)null))
			{
				TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
				if (((TMP_Text)component).text == text2 || force)
				{
					Instance._tooltip.SetActive(false);
					((TMP_Text)component).text = "";
				}
			}
		}

		public static void SetTab(string tabName, bool animated = true)
		{
			//IL_004d: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: 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_015e: Unknown result type (might be due to invalid IL or missing references)
			if (Instance == null)
			{
				return;
			}
			List<Tuple<string, GameObject>> tabPages = Instance._tabPages;
			GameObject tabBarButtonRow = Instance._tabBarButtonRow;
			int num = 0;
			for (int i = 0; i < tabPages.Count; i++)
			{
				tabPages[i].Deconstruct(out var item, out var item2);
				string text = item;
				GameObject val = item2;
				bool flag = tabName == text;
				if (animated)
				{
					SlideFadeToggleEffectExtensions.SetActiveAnimated(val, flag, PageHiddenOffset, 25f);
				}
				else
				{
					val.SetActive(flag);
				}
				UIUtils.UnfuckLayoutHack(val);
				if ((Object)(object)val != (Object)null && tabName == text)
				{
					_lastTabName = tabName;
					num = i;
				}
			}
			if ((Object)(object)tabBarButtonRow != (Object)null)
			{
				for (int j = 0; j < tabBarButtonRow.transform.childCount; j++)
				{
					bool flag2 = j == num;
					bool atLeft = j == 0;
					bool atRight = j + 1 == tabPages.Count;
					Sprite sprite = ConnectedButtonGroupSettingController.GetSprite(atLeft, atRight, flag2);
					Color color = (flag2 ? ThornModule.AccentColor : Color.white);
					Color color2 = (flag2 ? Color.black : Color.white);
					Transform child = tabBarButtonRow.transform.GetChild(j);
					Image val2 = ((child != null) ? ((Component)child).GetComponent<Image>() : null);
					GameObject val3 = ((child != null) ? UIUtils.FindRecursive(((Component)child).gameObject, "Text") : null);
					if (!((Object)(object)child == (Object)null) && !((Object)(object)val2 == (Object)null) && !((Object)(object)val3 == (Object)null))
					{
						val2.sprite = sprite;
						((Graphic)val2).color = color;
						((Graphic)val3.GetComponent<TextMeshProUGUI>()).color = color2;
					}
				}
			}
			Instance.PerformInitialFocus();
		}

		private void PerformInitialFocus()
		{
			if (_lastTabName == "Modules")
			{
				if ((Object)(object)_moduleSearchController != (Object)null)
				{
					_moduleSearchController.FocusSearch();
				}
			}
			else if (_lastTabName == "HUD" && (Object)(object)_hudModuleSearchController != (Object)null)
			{
				_hudModuleSearchController.FocusSearch();
			}
		}

		public static void CycleTab(int diff)
		{
			if (Instance != null && Instance._tabPages.Count != 0 && Instance.IsEnabled)
			{
				int num = Instance._tabPages.FindIndex((Tuple<string, GameObject> p) => p.Item1 == _lastTabName);
				if (num == -1)
				{
					num = 0;
				}
				int count = Instance._tabPages.Count;
				int index = ((num + diff) % count + count) % count;
				SetTab(Instance._tabPages[index].Item1);
			}
		}

		public static void NestPanel(GameObject panelContent)
		{
			//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_005f: 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_00b7: 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)
			if (Instance == null || (Object)(object)Instance._canvas == (Object)null || (Object)(object)_layoutedPagePrefab == (Object)null)
			{
				return;
			}
			GameObject val = Object.Instantiate<GameObject>(_layoutedPagePrefab, Instance._canvas.transform);
			AddToLayoutedPage(val, panelContent);
			RectTransform val2 = (RectTransform)panelContent.transform;
			val2.pivot = new Vector2(0.5f, 0.5f);
			((Transform)val2).localPosition = Vector3.zero;
			if ((Object)(object)Instance._tabBarButtonRow != (Object)null)
			{
				Instance._tabBarButtonRow.SetActive(false);
			}
			if (Instance._panelStack.Count > 0)
			{
				SlideFadeToggleEffectExtensions.SetActiveAnimated(Instance._panelStack.Peek(), false, PageHiddenOffset, 25f);
			}
			else
			{
				Instance._tabPages.ForEach(delegate(Tuple<string, GameObject> p)
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					SlideFadeToggleEffectExtensions.SetActiveAnimated(p.Item2, false, PageHiddenOffset, 25f);
				});
			}
			SlideFadeToggleEffectExtensions.SetActiveAnimated(val, true, PageHiddenOffset, 25f);
			Instance._panelStack.Push(val);
			SurrenderTooltipText("", force: true);
		}

		public static void SpawnContent(GameObject content)
		{
			if (Instance != null && !((Object)(object)content == (Object)null))
			{
				GameObject val = null;
				val = (GameObject)((Instance._panelStack.Count <= 0) ? ((object)Instance._tabPages.FirstOrDefault((Tuple<string, GameObject> p) => p.Item1 == _lastTabName)?.Item2) : ((object)Instance._panelStack.Peek()));
				if (!((Object)(object)val == (Object)null))
				{
					AddToLayoutedPage(val, content);
				}
			}
		}

		public static void NavigateBack()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			if (Instance == null || !Instance.IsEnabled)
			{
				return;
			}
			if (Instance._panelStack.Count > 0)
			{
				Object.Destroy((Object)(object)Instance._panelStack.Pop());
				if (Instance._panelStack.Count > 0)
				{
					SlideFadeToggleEffectExtensions.SetActiveAnimated(Instance._panelStack.Peek(), true, PageHiddenOffset, 25f);
				}
				else
				{
					SetTab(_lastTabName);
					if ((Object)(object)Instance._tabBarButtonRow != (Object)null)
					{
						Instance._tabBarButtonRow.SetActive(true);
					}
				}
			}
			else if (Instance.IsEnabled)
			{
				Instance.Toggle();
			}
			SurrenderTooltipText("", force: true);
		}

		public static void NestConfigPanel(Configurable? config)
		{
			if (config != null)
			{
				GameObject val = CreateConfigPanel(config);
				if ((Object)(object)val != (Object)null)
				{
					NestPanel(val);
				}
				SurrenderTooltipText("", force: true);
			}
		}

		private static GameObject? CreateConfigPanel(Configurable config)
		{
			if ((Object)(object)AssetManager.Get<GameObject>(BundleKey, "ModuleCategory") == (Object)null)
			{
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(BundleKey, "ModuleCategory"));
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			ConfigurableWindowController orAddComponent = GameObjectExtensions.GetOrAddComponent<ConfigurableWindowController>(val);
			orAddComponent.IsPopup = true;
			orAddComponent.TargetConfigurable = config;
			return val;
		}
	}
	internal static class PauseMenuButton
	{
		private const string PauseNotifToggleButtonName = "ThornToggleClickGUI";

		private static GameObject? _clickGuiToggleButton;

		public static void Initialize()
		{
		}

		static PauseMenuButton()
		{
			SceneUtils.SafeSceneLoadedNoParam += PatchPauseMenu;
		}

		private static void PatchPauseMenu()
		{
			//IL_0000: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Expected O, but got Unknown
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			GameObject val = (from obj in ((Scene)(ref activeScene)).GetRootGameObjects()
				where ((Object)obj).name == "Canvas"
				select obj).FirstOrDefault();
			if ((Object)(object)val == (Object)null || (Object)(object)_clickGuiToggleButton != (Object)null)
			{
				return;
			}
			GameObject val2 = UIUtils.FindRecursive(val, "PauseMenu");
			GameObject val3 = ((val2 != null) ? UIUtils.FindRecursive(val2, "Resume") : null);
			if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val3 == (Object)null))
			{
				_clickGuiToggleButton = Object.Instantiate<GameObject>(val3, val2.transform);
				((Object)_clickGuiToggleButton).name = "ThornToggleClickGUI";
				Button component = _clickGuiToggleButton.GetComponent<Button>();
				component.onClick = new ButtonClickedEvent();
				if (ClickGUI.Instance != null)
				{
					((UnityEvent)component.onClick).AddListener(new UnityAction(ClickGUI.Instance.Toggle));
				}
				GameObject val4 = UIUtils.FindRecursive(_clickGuiToggleButton, "Text");
				if ((Object)(object)val4 != (Object)null)
				{
					Object.Destroy((Object)(object)val4);
				}
				RectTransform component2 = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "ThornClickGUIToggleIcon"), _clickGuiToggleButton.transform).GetComponent<RectTransform>();
				component2.anchorMin = new Vector2(0.3f, 0.3f);
				component2.anchorMax = new Vector2(0.7f, 0.7f);
				UpdateAppearance();
			}
		}

		public static void UpdateAppearance()
		{
			//IL_0025: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_clickGuiToggleButton == (Object)null)
			{
				return;
			}
			RectTransform component = _clickGuiToggleButton.GetComponent<RectTransform>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			component.sizeDelta = new Vector2(component.sizeDelta.y, component.sizeDelta.y);
			ThornModule? instance = ThornModule.Instance;
			int num;
			int num2;
			if (instance == null)
			{
				num = 0;
			}
			else
			{
				num = (instance.MenuButtonPositionForceConfiggyNicePosition.Value ? 1 : 0);
				if (num != 0)
				{
					num2 = -115;
					goto IL_0063;
				}
			}
			num2 = -107;
			goto IL_0063;
			IL_0063:
			float num3 = num2;
			((Transform)component).localPosition = new Vector3(num3, -90f, 0f);
			if (num != 0)
			{
				GameObject val = UIUtils.FindRecursive(((Component)_clickGuiToggleButton.transform.parent).gameObject, "UI_Button_Image(Clone)");
				if ((Object)(object)val != (Object)null)
				{
					RectTransform component2 = val.GetComponent<RectTransform>();
					((Transform)component2).localPosition = new Vector3(115f, ((Transform)component2).localPosition.y, ((Transform)component2).localPosition.z);
				}
			}
		}
	}
	public class ThornModule : SystemModule
	{
		public static ThornModule? Instance;

		public static Color AccentColor => Instance?.Accent.Value ?? Color.white;

		public Setting<Keybind> OpenClickGUI { get; }

		public Setting<Keybind> SwitchTabLeft { get; }

		public Setting<Keybind> SwitchTabRight { get; }

		public Setting<Color> Accent { get; }

		public Setting<bool> MenuPausesGame { get; }

		public Setting<bool> MenuButtonPositionForceConfiggyNicePosition { get; }

		public Setting<string> LastVersion { get; }

		public override bool IsEnabled => true;

		public override Sprite Icon => AssetManager.Get<Sprite>(ClickGUI.BundleKey, "settings");

		public ThornModule()
			: base("thorn.thorn", "Thorn", "General settings")
		{
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			if (Instance != null)
			{
				return;
			}
			Instance = this;
			UserHints.Initialize();
			OpenClickGUI = CreateSetting("openClickGui", "Open menu keybind", "Keybind to open Thorn's ClickGUI interface", new Keybind((KeyCode)303, (KeyCode)0));
			OpenClickGUI.OnPress += delegate
			{
				if (ClickGUI.Instance != null)
				{
					ClickGUI.Instance.Toggle();
				}
			};
			SettingGroup parent = CreateGroup("otherBinds", "Other keybinds", "Less important keybinds are here");
			SwitchTabLeft = CreateSetting("switchTabLeft", "Switch to tab on the left", "Switch to tab on the left", new Keybind((KeyCode)280, (KeyCode)306), parent);
			SwitchTabLeft.OnPress += delegate
			{
				ClickGUI.CycleTab(-1);
			};
			SwitchTabRight = CreateSetting("switchTabRight", "Switch to tab on the right", "Switch to tab on the right", new Keybind((KeyCode)281, (KeyCode)306), parent);
			SwitchTabRight.OnPress += delegate
			{
				ClickGUI.CycleTab(1);
			};
			MenuPausesGame = CreateSetting("menuPausesGame", "Menu pauses game", "Makes the game paused when you open the ClickGUI", defaultValue: true);
			MenuButtonPositionForceConfiggyNicePosition = CreateSetting("menuButtonPosition", "Force nice menu button position", "Tries to move the Configgy button a bit so it has proper spacing", defaultValue: false);
			MenuButtonPositionForceConfiggyNicePosition.OnChanged += PauseMenuButton.UpdateAppearance;
			Accent = CreateSetting<Color>("accentColor", "Accent Color", "Color used for highlighting certain elements, preferably a bright one", new Color(0.65f, 0.95f, 0.89f));
			SettingGroup parent2 = CreateGroup("devGroup", "Developer", "Developer options, not so interesting");
			LastVersion = CreateSetting("lastVersion", "Last Thorn Version", "The version of Thorn run in the previous/current session", "0.0.0", parent2);
			CreateHeader("about", "About", "Thorn is an open-source, extensible utility mod for ULTRAKILL with a powerful configuration system.");
			ConfigButtonRow configButtonRow = CreateButtonRow("engagementButtons", "Links", "Links to Thorn stuff", new string[3] { "GitHub", "Docs 4 mod devs", "Donations" });
			configButtonRow.OnClick = (Action<int>)Delegate.Combine(configButtonRow.OnClick, (Action<int>)delegate(int i)
			{
				switch (i)
				{
				case 0:
					Application.OpenURL("https://github.com/end-4/ultrakill-thorn-client");
					break;
				case 1:
					Application.OpenURL("https://github.com/end-4/ultrakill-thorn-client/wiki");
					break;
				case 2:
					Application.OpenURL("https://github.com/sponsors/end-4");
					break;
				}
			});
			PauseMenuButton.Initialize();
		}

		public override void OnUpdate()
		{
		}
	}
	internal static class UserHints
	{
		internal static void SendLaunchNotifsIfNecessary()
		{
			ThornModule instance = ThornModule.Instance;
			if (instance != null)
			{
				Version value = new Version(instance.LastVersion.Value ?? "999.999.999");
				Version version = new Version("0.1.0");
				if (version.CompareTo(value) == 1)
				{
					instance.LastVersion.Value = version.ToString();
					NotificationSystem.NotifySend("Thorn::<color=#a5f2e2>Hello</color>", "To access the config menu, press " + instance.OpenClickGUI.Value.ToString(pretty: true), (Sprite)null, Path.Combine(Plugin.workingDir, "icon.png"), (Urgency)1, "NotifySend", 0u, (Dictionary<string, string>)null, 10000);
				}
				SceneManager.sceneLoaded -= SendLaunchNotifsIfNecessary;
			}
		}

		internal static void SendLaunchNotifsIfNecessary(Scene _, LoadSceneMode __)
		{
			SendLaunchNotifsIfNecessary();
		}

		internal static void Initialize()
		{
		}

		static UserHints()
		{
			SceneManager.sceneLoaded += SendLaunchNotifsIfNecessary;
		}
	}
}
namespace ThornClient.System.ClickGUIComponents
{
	internal class BoolSettingController : MonoBehaviour
	{
		public Setting<bool>? TargetSetting;

		private GameObject? _checkMark;

		private void Start()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			((UnityEvent)((Component)this).GetComponent<Button>().onClick).AddListener(new UnityAction(ToggleSetting));
			if (TargetSetting != null)
			{
				Setting<bool>? targetSetting = TargetSetting;
				targetSetting.OnValueChanged = (Action<bool>)Delegate.Combine(targetSetting.OnValueChanged, new Action<bool>(UpdateCheckmark));
				_checkMark = UIUtils.FindRecursive(((Component)this).gameObject, "Checkbox/Mark");
				UpdateCheckmark(TargetSetting.Value);
			}
		}

		private void OnDestroy()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			((UnityEvent)((Component)this).GetComponent<Button>().onClick).RemoveListener(new UnityAction(ToggleSetting));
			if (TargetSetting != null)
			{
				Setting<bool>? targetSetting = TargetSetting;
				targetSetting.OnValueChanged = (Action<bool>)Delegate.Remove(targetSetting.OnValueChanged, new Action<bool>(UpdateCheckmark));
			}
		}

		private void ToggleSetting()
		{
			if (TargetSetting != null)
			{
				TargetSetting.Value = !TargetSetting.Value;
			}
		}

		private void UpdateCheckmark(bool value)
		{
			if ((Object)(object)_checkMark != (Object)null)
			{
				_checkMark.SetActive(value);
			}
		}
	}
	internal class ButtonRowSettingController : MonoBehaviour
	{
		public ConfigButtonRow? TargetButtonRow;

		private void Start()
		{
			if (TargetButtonRow != null)
			{
				Populate();
			}
		}

		private void Populate()
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			if (TargetButtonRow == null)
			{
				return;
			}
			for (int i = 0; i < TargetButtonRow.Texts.Count; i++)
			{
				string text = TargetButtonRow.Texts[i];
				GameObject obj = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "ButtonRowButton"), ((Component)this).transform);
				GameObject val = UIUtils.FindRecursive(obj, "Text");
				if ((Object)(object)val != (Object)null)
				{
					((TMP_Text)val.GetComponent<TextMeshProUGUI>()).text = text;
				}
				int iCopied = i;
				((UnityEvent)obj.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
				{
					Trigger(iCopied);
				});
			}
		}

		private void Trigger(int idx)
		{
			if (TargetButtonRow != null)
			{
				TargetButtonRow.OnClick?.Invoke(idx);
			}
		}
	}
	internal class ClickGUITooltipHandler : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler
	{
		public string Text = "";

		public void OnPointerEnter(PointerEventData eventData)
		{
			ClickGUI.SetTooltipText(Text);
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			ClickGUI.SurrenderTooltipText(Text);
		}
	}
	public class Colorizer : MonoBehaviour
	{
		private TextMeshProUGUI? _textComp;

		private Image? _imageComp;

		private Color? _overrideColor;

		private Color? _overrideNormalColor;

		private bool _highlighted;

		public Color HighlightColor
		{
			get
			{
				//IL_0022: 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)
				return (Color)(((??)_overrideColor) ?? ThornModule.Instance.Accent.Value);
			}
			set
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)_imageComp == (Object)null)
				{
					_overrideColor = value;
				}
			}
		}

		public Color NormalColor
		{
			get
			{
				//IL_0018: 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)
				return (Color)(((??)_overrideNormalColor) ?? Color.white);
			}
			set
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				_overrideNormalColor = value;
			}
		}

		public bool Highlighted
		{
			get
			{
				return _highlighted;
			}
			set
			{
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: 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_0048: Unknown result type (might be due to invalid IL or missing references)
				_highlighted = value;
				Color color = (value ? HighlightColor : NormalColor);
				if ((Object)(object)_textComp != (Object)null)
				{
					((Graphic)_textComp).color = color;
				}
				else if ((Object)(object)_imageComp != (Object)null)
				{
					((Graphic)_imageComp).color = color;
				}
			}
		}

		private void Start()
		{
			_textComp = ((Component)this).GetComponent<TextMeshProUGUI>();
			_imageComp = ((Component)this).GetComponent<Image>();
			if (!_overrideColor.HasValue)
			{
				ThornModule.Instance.Accent.OnChanged += UpdateHighlight;
			}
			UpdateHighlight();
		}

		private void OnDestroy()
		{
			if (!_overrideColor.HasValue)
			{
				ThornModule.Instance.Accent.OnChanged -= UpdateHighlight;
			}
		}

		private void UpdateHighlight()
		{
			Highlighted = _highlighted;
		}
	}
	internal class ColorSettingController : MonoBehaviour
	{
		public Setting<Color>? TargetSetting;

		private Image? _colorPreview;

		private TMP_InputField? _hexInput;

		private Slider?[] _sliders;

		private TMP_InputField?[] _valueInputs;

		private void Start()
		{
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			if (TargetSetting == null)
			{
				return;
			}
			GameObject obj = UIUtils.FindRecursive(((Component)this).gameObject, "PickerRow/PreviewColumn/ColorBorder/ColorPreview");
			_colorPreview = ((obj != null) ? obj.GetComponent<Image>() : null);
			GameObject obj2 = UIUtils.FindRecursive(((Component)this).gameObject, "PickerRow/PreviewColumn/HexInput");
			_hexInput = ((obj2 != null) ? obj2.GetComponent<TMP_InputField>() : null);
			Slider[] array = new Slider[4];
			GameObject obj3 = UIUtils.FindRecursive(((Component)this).gameObject, "PickerRow/ValueColumn/Red/Slider");
			array[0] = ((obj3 != null) ? obj3.GetComponent<Slider>() : null);
			GameObject obj4 = UIUtils.FindRecursive(((Component)this).gameObject, "PickerRow/ValueColumn/Green/Slider");
			array[1] = ((obj4 != null) ? obj4.GetComponent<Slider>() : null);
			GameObject obj5 = UIUtils.FindRecursive(((Component)this).gameObject, "PickerRow/ValueColumn/Blue/Slider");
			array[2] = ((obj5 != null) ? obj5.GetComponent<Slider>() : null);
			GameObject obj6 = UIUtils.FindRecursive(((Component)this).gameObject, "PickerRow/ValueColumn/Alpha/Slider");
			array[3] = ((obj6 != null) ? obj6.GetComponent<Slider>() : null);
			_sliders = (Slider?[])(object)array;
			TMP_InputField[] array2 = new TMP_InputField[4];
			GameObject obj7 = UIUtils.FindRecursive(((Component)this).gameObject, "PickerRow/ValueColumn/Red/Input");
			array2[0] = ((obj7 != null) ? obj7.GetComponent<TMP_InputField>() : null);
			GameObject obj8 = UIUtils.FindRecursive(((Component)this).gameObject, "PickerRow/ValueColumn/Green/Input");
			array2[1] = ((obj8 != null) ? obj8.GetComponent<TMP_InputField>() : null);
			GameObject obj9 = UIUtils.FindRecursive(((Component)this).gameObject, "PickerRow/ValueColumn/Blue/Input");
			array2[2] = ((obj9 != null) ? obj9.GetComponent<TMP_InputField>() : null);
			GameObject obj10 = UIUtils.FindRecursive(((Component)this).gameObject, "PickerRow/ValueColumn/Alpha/Input");
			array2[3] = ((obj10 != null) ? obj10.GetComponent<TMP_InputField>() : null);
			_valueInputs = (TMP_InputField?[])(object)array2;
			if ((Object)(object)_hexInput != (Object)null)
			{
				((UnityEvent<string>)(object)_hexInput.onEndEdit).AddListener((UnityAction<string>)TrySaveNewHex);
				ComponentExtensions.GetOrAddComponent<InputFocusGrab>((Component)(object)_hexInput);
			}
			for (int i = 0; i < _sliders.Length; i++)
			{
				Slider val = _sliders[i];
				if ((Object)(object)val != (Object)null)
				{
					val.minValue = 0f;
					val.maxValue = 1f;
					int i2 = i;
					((UnityEvent<float>)(object)val.onValueChanged).AddListener((UnityAction<float>)delegate(float value)
					{
						TrySaveNewValue(value, i2);
					});
				}
			}
			for (int num = 0; num < _valueInputs.Length; num++)
			{
				TMP_InputField val2 = _valueInputs[num];
				ComponentExtensions.GetOrAddComponent<InputFocusGrab>((Component)(object)val2);
				if (!((Object)(object)val2 != (Object)null))
				{
					continue;
				}
				int i3 = num;
				((UnityEvent<string>)(object)val2.onValueChanged).AddListener((UnityAction<string>)delegate(string s)
				{
					if (int.TryParse(s, out var result))
					{
						TrySaveNewValue((float)result / 255f, i3);
					}
				});
			}
			Setting<Color>? targetSetting = TargetSetting;
			targetSetting.OnValueChanged = (Action<Color>)Delegate.Combine(targetSetting.OnValueChanged, new Action<Color>(UpdateDisplay));
			UpdateDisplay(TargetSetting.Value);
		}

		private void TrySaveNewHex(string hex)
		{
			//IL_006d: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			if (TargetSetting != null)
			{
				if (!hex.StartsWith("#"))
				{
					hex = "#" + hex;
				}
				Color val = default(Color);
				if (ColorUtility.TryParseHtmlString(hex, ref val))
				{
					TargetSetting.Value = new Color(val.r, val.g, val.b, TargetSetting.Value.a);
				}
				else
				{
					TargetSetting.Value = new Color(TargetSetting.Value.r, TargetSetting.Value.g, TargetSetting.Value.b, TargetSetting.Value.a);
				}
				UpdateDisplay(TargetSetting.Value);
			}
		}

		private void TrySaveNewValue(float value, int index)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			if (TargetSetting != null)
			{
				float[] source = new float[4] { 0f, 1f, 2f, 3f };
				source = source.Select((float i) => ((int)i != index) ? ColorUtils.GetValues(TargetSetting.Value)[(int)i] : value).ToArray();
				TargetSetting.Value = new Color(source[0], source[1], source[2], source[3]);
			}
		}

		private void OnDestroy()
		{
			if (TargetSetting != null)
			{
				Setting<Color>? targetSetting = TargetSetting;
				targetSetting.OnValueChanged = (Action<Color>)Delegate.Remove(targetSetting.OnValueChanged, new Action<Color>(UpdateDisplay));
			}
		}

		private void UpdateDisplay(Color col)
		{
			//IL_0023: 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_005d: 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_006f: 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)
			if (TargetSetting == null)
			{
				return;
			}
			if ((Object)(object)_colorPreview != (Object)null)
			{
				((Graphic)_colorPreview).color = TargetSetting.Value;
			}
			if ((Object)(object)_hexInput != (Object)null)
			{
				_hexInput.text = ColorUtility.ToHtmlStringRGB(col);
			}
			float[] array = new float[4] { col.r, col.g, col.b, col.a };
			for (int i = 0; i < _sliders.Length; i++)
			{
				Slider val = _sliders[i];
				if ((Object)(object)val != (Object)null)
				{
					val.value = array[i];
				}
			}
			for (int j = 0; j < _valueInputs.Length; j++)
			{
				TMP_InputField val2 = _valueInputs[j];
				if ((Object)(object)val2 != (Object)null)
				{
					val2.text = $"{(int)(255f * array[j])}";
				}
			}
			UIUtils.UnfuckLayoutHack(((Component)this).gameObject);
		}
	}
	public static class ConfigurableElementUICreators
	{
		public static readonly Dictionary<SettingType, Func<Setting, Transform, GameObject>> SettingUICreators = new Dictionary<SettingType, Func<Setting, Transform, GameObject>>
		{
			[SettingType.Bind] = delegate(Setting setting, Transform parent)
			{
				GameObject obj = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "KeybindSetting"), parent);
				obj.AddComponent<KeybindSettingController>().TargetSetting = (Setting<Keybind>)setting;
				return obj;
			},
			[SettingType.Bool] = delegate(Setting setting, Transform parent)
			{
				InterfaceHints? hints = setting.Hints;
				if ((object)hints != null && hints.BoolPreferCheckmark == true)
				{
					GameObject obj = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "BoolSetting"), parent);
					obj.AddComponent<BoolSettingController>().TargetSetting = (Setting<bool>)setting;
					return obj;
				}
				GameObject obj2 = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "SwitchBoolSetting"), parent);
				obj2.AddComponent<SwitchBoolSettingController>().TargetSetting = (Setting<bool>)setting;
				return obj2;
			},
			[SettingType.Color] = delegate(Setting setting, Transform parent)
			{
				GameObject obj = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "ColorSetting"), parent);
				obj.AddComponent<ColorSettingController>().TargetSetting = (Setting<Color>)setting;
				return obj;
			},
			[SettingType.EnemyList] = delegate(Setting setting, Transform parent)
			{
				GameObject obj = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "EnemyListSetting"), parent);
				obj.AddComponent<EnemyListSettingController>().TargetSetting = (Setting<EnemyList>)setting;
				return obj;
			},
			[SettingType.Enum] = delegate(Setting setting, Transform parent)
			{
				int num = Enum.GetNames(setting.GetValue().GetType()).Sum((string name) => name.Length);
				InterfaceHints? hints = setting.Hints;
				if ((object)hints == null || hints.EnumPreferButtonGroup != true)
				{
					if (num <= 20)
					{
						InterfaceHints? hints2 = setting.Hints;
						if ((object)hints2 == null || hints2.EnumPreferButtonGroup != false)
						{
							goto IL_007f;
						}
					}
					GameObject obj = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "DropdownSetting"), parent);
					obj.AddComponent<DropdownSettingController>().TargetSetting = setting;
					return obj;
				}
				goto IL_007f;
				IL_007f:
				GameObject obj2 = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "ConnectedButtonGroupSetting"), parent);
				obj2.AddComponent<ConnectedButtonGroupSettingController>().TargetSetting = setting;
				return obj2;
			},
			[SettingType.Float] = delegate(Setting setting, Transform parent)
			{
				GameObject obj = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "NumberSetting"), parent);
				obj.AddComponent<FloatSettingController>().TargetSetting = (Setting<float>)setting;
				return obj;
			},
			[SettingType.Int] = delegate(Setting setting, Transform parent)
			{
				GameObject obj = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "NumberSetting"), parent);
				obj.AddComponent<IntSettingController>().TargetSetting = (Setting<int>)setting;
				return obj;
			},
			[SettingType.Text] = delegate(Setting setting, Transform parent)
			{
				GameObject obj = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "TextSetting"), parent);
				obj.AddComponent<TextSettingController>().TargetSetting = (Setting<string>)setting;
				return obj;
			}
		};

		public static readonly Dictionary<Type, Func<IConfigurableElement, Transform, GameObject>> MenuUICreators = new Dictionary<Type, Func<IConfigurableElement, Transform, GameObject>>
		{
			[typeof(ConfigButtonRow)] = delegate(IConfigurableElement configurableElement, Transform parent)
			{
				GameObject obj = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "ButtonRowSetting"), parent);
				obj.AddComponent<ButtonRowSettingController>().TargetButtonRow = (ConfigButtonRow)configurableElement;
				return obj;
			},
			[typeof(SettingGroup)] = delegate(IConfigurableElement configurableElement, Transform parent)
			{
				GameObject obj = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "WindowedGroupSetting"), parent);
				obj.AddComponent<WindowedGroupSettingController>().TargetGroup = (SettingGroup)configurableElement;
				return obj;
			},
			[typeof(ConfigHeader)] = delegate(IConfigurableElement configurableElement, Transform parent)
			{
				GameObject obj = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "HeaderSetting"), parent);
				obj.AddComponent<HeaderSettingController>().TargetElement = (ConfigHeader)configurableElement;
				return obj;
			}
		};
	}
	internal class ConfigurableWindowController : MonoBehaviour
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__NavigateBack;
		}

		private bool _doneSetup;

		public bool IsPopup;

		public Configurable? TargetConfigurable;

		private void Start()
		{
			SetupStuff();
		}

		public void SetupStuff()
		{
			//IL_011e: 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: Expected O, but got Unknown
			if (_doneSetup)
			{
				return;
			}
			_doneSetup = true;
			if (TargetConfigurable == null)
			{
				return;
			}
			GameObject obj = UIUtils.FindRecursive(((Component)this).gameObject, "Header/TitleButton/TitleIcon");
			Image val = ((obj != null) ? obj.GetComponent<Image>() : null);
			GameObject obj2 = UIUtils.FindRecursive(((Component)this).gameObject, "Header/TitleName");
			TextMeshProUGUI obj3 = ((obj2 != null) ? obj2.GetComponent<TextMeshProUGUI>() : null);
			if (TargetConfigurable is ThornClient.Core.Module module && (Object)(object)val != (Object)null)
			{
				val.sprite = module.Icon;
			}
			((TMP_Text)obj3).text = TargetConfigurable.Name;
			GameObject obj4 = UIUtils.FindRecursive(((Component)this).gameObject, "Header");
			if (obj4 != null)
			{
				obj4.AddComponent<TitlebarDragHandler>();
			}
			GameObject obj5 = UIUtils.FindRecursive(((Component)this).gameObject, "Header/TitleButton");
			Button val2 = ((obj5 != null) ? obj5.GetComponent<Button>() : null);
			((Selectable)UIUtils.FindRecursive(((Component)this).gameObject, "Header/TitleButton").GetComponent<Button>()).interactable = IsPopup;
			GameObject obj6 = UIUtils.FindRecursive(((Component)this).gameObject, "Header/TitleButton/BackIcon");
			if (obj6 != null)
			{
				obj6.SetActive(IsPopup);
			}
			if (IsPopup)
			{
				ButtonClickedEvent onClick = val2.onClick;
				object obj7 = <>O.<0>__NavigateBack;
				if (obj7 == null)
				{
					UnityAction val3 = ClickGUI.NavigateBack;
					<>O.<0>__NavigateBack = val3;
					obj7 = (object)val3;
				}
				((UnityEvent)onClick).AddListener((UnityAction)obj7);
			}
			Transform transform = UIUtils.FindRecursive(((Component)this).gameObject, "Scroll View/Viewport/Content/Modules").transform;
			((TMP_Text)UIUtils.FindRecursive(Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "ModuleDescription"), transform), "DescText").GetComponent<TextMeshProUGUI>()).text = TargetConfigurable.Description;
			if (!(TargetConfigurable is SystemModule))
			{
				Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "EnabledButton"), transform).AddComponent<EnabledButtonController>().Configurable = TargetConfigurable;
			}
			if (TargetConfigurable is HudModule hudModule)
			{
				HudElementPositioningController hudElementPositioningController = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "RemoteDrag"), transform).AddComponent<HudElementPositioningController>();
				hudElementPositioningController.TargetModule = hudModule;
				if ((Object)(object)hudModule.UIElement != (Object)null)
				{
					ref RectTransform? target = ref hudElementPositioningController.target;
					Transform transform2 = hudModule.UIElement.transform;
					target = (RectTransform?)(object)((transform2 is RectTransform) ? transform2 : null);
				}
			}
			Populate(transform, TargetConfigurable.Elements);
			UIUtils.UnfuckLayoutHack(((Component)this).gameObject);
		}

		private void Populate(Transform parent, IEnumerable<IConfigurableElement> elements)
		{
			foreach (IConfigurableElement element in elements)
			{
				GameObject val = null;
				if (element is Setting setting)
				{
					val = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "SettingRowWrapper"), parent);
					val.AddComponent<SettingRowController>().TargetSetting = setting;
					if (ConfigurableElementUICreators.SettingUICreators.TryGetValue(setting.Type, out Func<Setting, Transform, GameObject> value))
					{
						value(setting, val.transform).AddComponent<SettingDescriptionController>().TargetSetting = setting;
					}
				}
				else if ((element is SettingGroup || element is ConfigButtonRow || element is ConfigHeader) ? true : false)
				{
					val = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "SettingRowWrapper"), parent);
					if (ConfigurableElementUICreators.MenuUICreators.TryGetValue(element.GetType(), out Func<IConfigurableElement, Transform, GameObject> value2))
					{
						GameObject val2 = value2(element, val.transform);
						if (!(element is ConfigHeader))
						{
							val2.AddComponent<SettingDescriptionController>().TargetSetting = element;
						}
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					UIUtils.UnfuckLayoutHack(val);
					if (element.Hints?.Hidden == true)
					{
						val.SetActive(false);
					}
				}
			}
		}
	}
	internal class ConnectedButtonGroupSettingController : MonoBehaviour
	{
		private Type? _enumType;

		private GameObject? _btnRow;

		private string[] _enumNames = Array.Empty<string>();

		private readonly List<(Image image, TMP_Text text)> _cachedButtons = new List<(Image, TMP_Text)>();

		public Setting? TargetSetting { get; set; }

		private void Start()
		{
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Expected O, but got Unknown
			if (TargetSetting == null)
			{
				return;
			}
			object value = TargetSetting.GetValue();
			_enumType = value.GetType();
			if (!_enumType.IsEnum)
			{
				Plugin.Log.LogError((object)("[EnumSettingController] Setting " + TargetSetting.Name + " is not an enum!"));
				return;
			}
			TargetSetting.OnChanged += UpdateDisplay;
			_btnRow = UIUtils.FindRecursive(((Component)this).gameObject, "ButtonRow");
			if ((Object)(object)_btnRow != (Object)null)
			{
				_enumNames = Enum.GetNames(_enumType);
				_cachedButtons.Clear();
				for (int i = 0; i < _enumNames.Length; i++)
				{
					GameObject obj = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "ConnectedChoiceButton"), _btnRow.transform);
					TMP_Text component = UIUtils.FindRecursive(obj, "Text").GetComponent<TMP_Text>();
					Image component2 = obj.GetComponent<Image>();
					component.text = _enumNames[i];
					_cachedButtons.Add((component2, component));
					int i2 = i;
					((UnityEvent)obj.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
					{
						TargetSetting.SetValue(Enum.Parse(_enumType, _enumNames[i2]));
					});
				}
			}
			UpdateDisplay();
		}

		private void UpdateDisplay()
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: 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)
			if (TargetSetting == null || _enumType == null || _cachedButtons.Count == 0)
			{
				return;
			}
			string text = TargetSetting.GetValue().ToString();
			int count = _cachedButtons.Count;
			for (int i = 0; i < count; i++)
			{
				(Image image, TMP_Text text) tuple = _cachedButtons[i];
				Image item = tuple.image;
				TMP_Text item2 = tuple.text;
				bool flag = _enumNames[i] == text;
				bool atLeft = i == 0;
				bool atRight = i == count - 1;
				Color val = (flag ? ThornModule.AccentColor : Color.white);
				Color val2 = (flag ? Color.black : Color.white);
				item.sprite = GetSprite(atLeft, atRight, flag);
				if (((Graphic)item).color != val)
				{
					((Graphic)item).color = val;
				}
				if (((Graphic)item2).color != val2)
				{
					((Graphic)item2).color = val2;
				}
			}
		}

		private void OnDestroy()
		{
			if (TargetSetting != null)
			{
				TargetSetting.OnChanged -= UpdateDisplay;
			}
		}

		public static Sprite GetSprite(bool atLeft, bool atRight, bool active)
		{
			string assetName = ((atLeft || atRight) ? "Round_" : "") + (active ? "Fill" : "Border") + "Large" + (atLeft ? "Left" : (atRight ? "Right" : ""));
			return AssetManager.Get<Sprite>(ClickGUI.BundleKey, assetName);
		}
	}
	internal class DropdownSettingController : MonoBehaviour
	{
		private TMP_Dropdown? _dropdown;

		private Type? _enumType;

		public Setting? TargetSetting { get; set; }

		private void Start()
		{
			if (TargetSetting == null)
			{
				return;
			}
			object value = TargetSetting.GetValue();
			_enumType = value.GetType();
			if (!_enumType.IsEnum)
			{
				Plugin.Log.LogError((object)("[EnumSettingController] Setting " + TargetSetting.Name + " is not an enum!"));
				return;
			}
			_dropdown = UIUtils.FindRecursive(((Component)this).gameObject, "Dropdown").GetComponent<TMP_Dropdown>();
			if ((Object)(object)_dropdown != (Object)null)
			{
				string[] names = Enum.GetNames(_enumType);
				_dropdown.ClearOptions();
				_dropdown.AddOptions(names.ToList());
				((UnityEvent<int>)(object)_dropdown.onValueChanged).AddListener((UnityAction<int>)OnDropdownValueChanged);
			}
			UpdateDisplay();
			TargetSetting.OnChanged += UpdateDisplay;
		}

		private void UpdateDisplay()
		{
			if (TargetSetting != null && !((Object)(object)_dropdown == (Object)null) && !(_enumType == null))
			{
				object value = TargetSetting.GetValue();
				int num = Array.IndexOf<string>(Enum.GetNames(_enumType), value.ToString());
				if (num >= 0)
				{
					_dropdown.value = num;
					_dropdown.RefreshShownValue();
				}
			}
		}

		private void OnDropdownValueChanged(int index)
		{
			string text = _dropdown.options[index].text;
			object value = Enum.Parse(_enumType, text);
			TargetSetting?.SetValue(value);
		}

		private void OnDestroy()
		{
			if (TargetSetting != null)
			{
				TargetSetting.OnChanged -= UpdateDisplay;
			}
			if ((Object)(object)_dropdown != (Object)null)
			{
				((UnityEvent<int>)(object)_dropdown.onValueChanged).RemoveListener((UnityAction<int>)OnDropdownValueChanged);
			}
		}
	}
	internal class EnabledButtonController : MonoBehaviour
	{
		public Configurable? Configurable;

		private TextMeshProUGUI? _textComp;

		private Image? _buttonImageComp;

		private Colorizer? _colorizer;

		private void Start()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			if (Configurable != null)
			{
				((UnityEvent)((Component)this).GetComponent<Button>().onClick).AddListener(new UnityAction(ToggleIt));
				GameObject obj = UIUtils.FindRecursive(((Component)this).gameObject, "Text");
				_textComp = ((obj != null) ? obj.GetComponent<TextMeshProUGUI>() : null);
				_buttonImageComp = ((Component)this).gameObject.GetComponent<Image>();
				_colorizer = GameObjectExtensions.GetOrAddComponent<Colorizer>(((Component)this).gameObject);
				Configurable.OnToggleStateChanged += UpdateAppearance;
				UpdateAppearance(Configurable.IsEnabled);
			}
		}

		private void OnDestroy()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			if (Configurable != null)
			{
				((UnityEvent)((Component)this).GetComponent<Button>().onClick).RemoveListener(new UnityAction(ToggleIt));
				Configurable.OnToggleStateChanged -= UpdateAppearance;
			}
		}

		private void ToggleIt()
		{
			Configurable?.Toggle();
		}

		private void UpdateAppearance(bool isEnabled)
		{
			//IL_0038: 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)
			if ((Object)(object)_textComp != (Object)null)
			{
				((TMP_Text)_textComp).text = (isEnabled ? "Enabled" : "Disabled");
				((Graphic)_textComp).color = (isEnabled ? Color.black : Color.white);
			}
			if ((Object)(object)_buttonImageComp != (Object)null)
			{
				_buttonImageComp.sprite = AssetManager.Get<Sprite>(ClickGUI.BundleKey, isEnabled ? "Round_FillLarge" : "Round_BorderLarge");
			}
			if ((Object)(object)_colorizer != (Object)null)
			{
				_colorizer.Highlighted = isEnabled;
			}
		}
	}
	internal class EnemyListController : MonoBehaviour
	{
		private bool _doneSetup;

		public bool IsPopup = true;

		public Setting<EnemyList>? TargetList;

		private Transform? _falseList;

		private Transform? _trueList;

		private void Start()
		{
			UIUtils.FindRecursive(((Component)this).gameObject, "Header").AddComponent<TitlebarDragHandler>();
			SetupModules();
		}

		public void SetupModules()
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			if (_doneSetup)
			{
				return;
			}
			_doneSetup = true;
			if (TargetList != null)
			{
				((TMP_Text)UIUtils.FindRecursive(((Component)this).gameObject, "Header/TitleName").GetComponent<TextMeshProUGUI>()).text = TargetList.Name;
				((UnityEvent)UIUtils.FindRecursive(((Component)this).gameObject, "Header/TitleButton").GetComponent<Button>().onClick).AddListener((UnityAction)delegate
				{
					Object.Destroy((Object)(object)((Component)this).gameObject);
				});
				_falseList = UIUtils.FindRecursive(((Component)this).gameObject, "Columns/FalseScrollView/Viewport/Content").transform;
				_trueList = UIUtils.FindRecursive(((Component)this).gameObject, "Columns/TrueScrollView/Viewport/Content").transform;
				PopulateLists();
				Setting<EnemyList>? targetList = TargetList;
				targetList.OnValueChanged = (Action<EnemyList>)Delegate.Combine(targetList.OnValueChanged, (Action<EnemyList>)delegate
				{
					PopulateLists();
				});
			}
		}

		private void OnDestroy()
		{
			if (TargetList != null)
			{
				Setting<EnemyList>? targetList = TargetList;
				targetList.OnValueChanged = (Action<EnemyList>)Delegate.Remove(targetList.OnValueChanged, (Action<EnemyList>)delegate
				{
					PopulateLists();
				});
			}
		}

		private unsafe void PopulateLists()
		{
			//IL_0039: 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_00f3: 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_0109: 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_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Expected O, but got Unknown
			if (TargetList == null || (Object)(object)_falseList == (Object)null || (Object)(object)_trueList == (Object)null)
			{
				return;
			}
			foreach (Transform @false in _falseList)
			{
				Object.Destroy((Object)(object)((Component)@false).gameObject);
			}
			foreach (Transform @true in _trueList)
			{
				Object.Destroy((Object)(object)((Component)@true).gameObject);
			}
			foreach (EnemyType enemyType in ((EnemyType[])Enum.GetValues(typeof(EnemyType))).OrderBy((EnemyType e) => ((object)(*(EnemyType*)(&e))/*cast due to .constrained prefix*/).ToString()))
			{
				bool flag = TargetList.Value.Includes(enemyType);
				Transform val = (flag ? _trueList : _falseList);
				GameObject obj = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "EnemyListItem"), val);
				UIUtils.FindRecursive(obj, "Icon").AddComponent<EnemyIconController>().enemyType = enemyType;
				((TMP_Text)UIUtils.FindRecursive(obj, "Name").GetComponent<TextMeshProUGUI>()).text = ((object)Unsafe.As<EnemyType, EnemyType>(ref enemyType)/*cast due to .constrained prefix*/).ToString();
				UIUtils.FindRecursive(obj, "ToggleButton/Icon").GetComponent<Image>().sprite = AssetManager.Get<Sprite>(ClickGUI.BundleKey, flag ? "minus" : "plus");
				((UnityEvent)UIUtils.FindRecursive(obj, "ToggleButton").GetComponent<Button>().onClick).AddListener((UnityAction)delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					OnItemClick(enemyType);
				});
				UIUtils.UnfuckLayoutHack(obj);
			}
			UIUtils.UnfuckLayoutHack(((Component)_falseList).gameObject);
			UIUtils.UnfuckLayoutHack(((Component)_trueList).gameObject);
			UIUtils.UnfuckLayoutHack(((Component)this).gameObject);
		}

		private void OnItemClick(EnemyType enemyType)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (TargetList != null)
			{
				EnemyList enemyList = TargetList.Value.Clone();
				enemyList.Toggle(enemyType);
				TargetList.Value = enemyList;
			}
		}
	}
	internal class EnemyListSettingController : MonoBehaviour
	{
		public Setting<EnemyList>? TargetSetting;

		private TextMeshProUGUI? text;

		private void Start()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			if (TargetSetting != null)
			{
				((UnityEvent)((Component)this).GetComponent<Button>().onClick).AddListener(new UnityAction(OpenList));
				text = UIUtils.FindRecursive(((Component)this).gameObject, "Name").GetComponent<TextMeshProUGUI>();
				Setting<EnemyList>? targetSetting = TargetSetting;
				targetSetting.OnValueChanged = (Action<EnemyList>)Delegate.Combine(targetSetting.OnValueChanged, new Action<EnemyList>(UpdateText));
				UpdateText(TargetSetting.Value);
			}
		}

		private void UpdateText(EnemyList elist)
		{
			if ((Object)(object)text != (Object)null && TargetSetting != null)
			{
				((TMP_Text)text).text = $"{TargetSetting.Name} ({elist.Count()})";
			}
		}

		private void OnDestroy()
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			if (TargetSetting != null)
			{
				Setting<EnemyList>? targetSetting = TargetSetting;
				targetSetting.OnValueChanged = (Action<EnemyList>)Delegate.Remove(targetSetting.OnValueChanged, new Action<EnemyList>(UpdateText));
			}
			Button component = ((Component)this).GetComponent<Button>();
			if ((Object)(object)component != (Object)null)
			{
				((UnityEvent)component.onClick).RemoveListener(new UnityAction(OpenList));
			}
		}

		private void OpenList()
		{
			GameObject val = CreateConfigPanel(TargetSetting);
			if ((Object)(object)val != (Object)null)
			{
				ClickGUI.SpawnContent(val);
			}
			ClickGUI.SurrenderTooltipText(TargetSetting?.Description ?? "");
		}

		private GameObject? CreateConfigPanel(Setting<EnemyList>? setting)
		{
			GameObject val = AssetManager.Get<GameObject>(ClickGUI.BundleKey, "EnemyList");
			if ((Object)(object)val == (Object)null || setting == null)
			{
				return null;
			}
			GameObject val2 = Object.Instantiate<GameObject>(val);
			if ((Object)(object)val2 == (Object)null)
			{
				return null;
			}
			EnemyListController orAddComponent = GameObjectExtensions.GetOrAddComponent<EnemyListController>(val2);
			orAddComponent.IsPopup = true;
			orAddComponent.TargetList = setting;
			return val2;
		}
	}
	internal class FloatSettingController : NumberSettingController<float>
	{
		protected override void UpdateScrub(float baseValue, float valueDiff)
		{
			if (TargetSetting != null)
			{
				TargetSetting.Value = baseValue + valueDiff;
			}
		}
	}
	internal class FreeMoveDragHandler : MonoBehaviour, IDragHandler, IEventSystemHandler
	{
		public RectTransform? target;

		protected Canvas? _canvas;

		private void Awake()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			try
			{
				if ((Object)(object)target == (Object)null)
				{
					target = (RectTransform)((Component)this).transform;
				}
				_canvas = ((Component)target).GetComponentInParent<Canvas>();
			}
			catch (Exception)
			{
				Plugin.Log.LogWarning((object)"[FreeMoveDragHandler] may have been added to a root element");
			}
		}

		public virtual void OnDrag(PointerEventData eventData)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_0044: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)target == (Object)null))
			{
				float num = (((Object)(object)_canvas != (Object)null) ? _canvas.scaleFactor : 1f);
				Vector2 val = eventData.delta / num;
				RectTransform? obj = target;
				obj.anchoredPosition += val;
			}
		}
	}
	internal class HeaderSettingController : MonoBehaviour
	{
		public ConfigHeader? TargetElement;

		private void Start()
		{
			if (TargetElement != null)
			{
				GameObject obj = UIUtils.FindRecursive(((Component)this).gameObject, "Name", false);
				TextMeshProUGUI val = ((obj != null) ? obj.GetComponent<TextMeshProUGUI>() : null);
				if ((Object)(object)val != (Object)null)
				{
					((TMP_Text)val).text = TargetElement.Name;
					((TMP_Text)val).fontSize = TargetElement.FontSize;
				}
				GameObject obj2 = UIUtils.FindRecursive(((Component)this).gameObject, "DescLayout/Description", false);
				TextMeshProUGUI val2 = ((obj2 != null) ? obj2.GetComponent<TextMeshProUGUI>() : null);
				if ((Object)(object)val2 != (Object)null)
				{
					((TMP_Text)val2).text = TargetElement.Description;
				}
				GameObject val3 = UIUtils.FindRecursive(((Component)((Component)this).transform.parent).gameObject, "RevertButtonWrapper");
				if ((Object)(object)val3 != (Object)null)
				{
					val3.SetActive(false);
				}
			}
		}
	}
	internal class InputFocusGrab : MonoBehaviour
	{
		private TMP_InputField? _input;

		private void OnEnable()
		{
			_input = ((Component)this).gameObject.GetComponent<TMP_InputField>();
			if (!((Object)(object)_input == (Object)null))
			{
				((UnityEvent<string>)(object)_input.onSelect).AddListener((UnityAction<string>)Grab);
				((UnityEvent<string>)(object)_input.onDeselect).AddListener((UnityAction<string>)Release);
			}
		}

		private void OnDisable()
		{
			if (!((Object)(object)_input == (Object)null))
			{
				((UnityEvent<string>)(object)_input.onSelect).RemoveListener((UnityAction<string>)Grab);
				((UnityEvent<string>)(object)_input.onDeselect).RemoveListener((UnityAction<string>)Release);
			}
		}

		private void Grab(string _)
		{
			InputManager.BlockInput = true;
		}

		private void Release(string _)
		{
			InputManager.BlockInput = false;
		}
	}
	internal class IntSettingController : NumberSettingController<int>
	{
		protected override void UpdateScrub(int baseValue, float valueDiff)
		{
			if (TargetSetting != null)
			{
				TargetSetting.Value = (int)((float)baseValue + valueDiff);
			}
		}
	}
	internal class KeybindSettingController : MonoBehaviour
	{
		private const string PauseKey = "Thorn_ClickGUI_KeybindListener";

		private static readonly Color NormalColor = new Color(1f, 1f, 1f);

		private static KeybindSettingController? _listeningInstance = null;

		private Button? _activateButton;

		private Colorizer? _keyBorder;

		private TextMeshProUGUI? _displayText;

		public Setting<Keybind> TargetSetting;

		private KeyCode _caughtModifier;

		private KeyCode _caughtKey;

		private static Color ListeningColor => (Color)(((??)ThornModule.Instance?.Accent.Value) ?? new Color(1f, 0.4048f, 0f));

		private static OptionsManager? opts => MonoSingleton<OptionsManager>.Instance;

		private void Start()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			_activateButton = ((Component)this).gameObject.GetComponent<Button>();
			_keyBorder = GameObjectExtensions.GetOrAddComponent<Colorizer>(UIUtils.FindRecursive(((Component)this).gameObject, "ValueDisplay"));
			GameObject obj = UIUtils.FindRecursive(((Component)this).gameObject, "ValueDisplay/Text");
			_displayText = ((obj != null) ? obj.GetComponent<TextMeshProUGUI>() : null);
			((UnityEvent)_activateButton.onClick).AddListener(new UnityAction(ActivateKeyListen));
			UpdateKeyDisplay();
			Setting<Keybind> targetSetting = TargetSetting;
			targetSetting.OnValueChanged = (Action<Keybind>)Delegate.Combine(targetSetting.OnValueChanged, new Action<Keybind>(UpdateKeyDisplay));
		}

		private void SetBorderColor(bool highlighted)
		{
			if (!((Object)(object)_keyBorder == (Object)null))
			{
				_keyBorder.Highlighted = highlighted;
			}
		}

		private void ActivateKeyListen()
		{
			//IL_0038: 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)
			InputManager.BlockInput = true;
			Pauser.Pause(true, "Thorn_ClickGUI_KeybindListener");
			if ((Object)(object)_listeningInstance != (Object)null)
			{
				_listeningInstance.SetBorderColor(highlighted: false);
			}
			_listeningInstance = this;
			SetBorderColor(highlighted: true);
			_caughtModifier = (KeyCode)0;
			_caughtKey = (KeyCode)0;
		}

		private void DeactivateKeyListen()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_003d: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			InputManager.BlockInput = false;
			GameStateManager.Instance.PopState("Thorn_ClickGUI_KeybindListener");
			if (IsListening())
			{
				_listeningInstance = null;
				SetBorderColor(highlighted: false);
				if ((int)_caughtModifier != 0 && (int)_caughtKey == 0)
				{
					_caughtKey = _caughtModifier;
					_caughtModifier = (KeyCode)0;
				}
				TargetSetting.Value = new Keybind(_caughtKey, _caughtModifier);
			}
		}

		private bool IsListening()
		{
			return (Object)(object)_listeningInstance == (Object)(object)this;
		}

		private unsafe void UpdateKeyDisplay()
		{
			//IL_0022: 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_0027: 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_0035: 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_0043: 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)
			string text = "";
			bool num = IsListening();
			KeyCode val = (num ? _caughtModifier : TargetSetting.Value.Modifier);
			KeyCode val2 = (num ? _caughtKey : TargetSetting.Value.Key);
			if ((int)val != 0)
			{
				text += ((object)(*(KeyCode*)(&val))/*cast due to .constrained prefix*/).ToString();
			}
			if ((int)val2 != 0)
			{
				if (text.Length > 0)
				{
					text += "+";
				}
				text += ((object)(*(KeyCode*)(&val2))/*cast due to .constrained prefix*/).ToString();
			}
			if (text.Length == 0)
			{
				text = "--";
			}
			if (((TMP_Text)_displayText).text != text)
			{
				((TMP_Text)_displayText).text = text;
			}
			UIUtils.UnfuckLayoutHack(((Component)this).gameObject);
		}

		private void UpdateKeyDisplay(Keybind _)
		{
			UpdateKeyDisplay();
		}

		private void OnDestroy()
		{
			DeactivateKeyListen();
			Setting<Keybind> targetSetting = TargetSetting;
			targetSetting.OnValueChanged = (Action<Keybind>)Delegate.Remove(targetSetting.OnValueChanged, new Action<Keybind>(UpdateKeyDisplay));
		}

		private void OnGUI()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Invalid comparison between Unknown and I4
			//IL_0018: 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_0037: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Invalid comparison between Unknown and I4
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Invalid comparison between Unknown and I4
			//IL_0087: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Invalid comparison between Unknown and I4
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Invalid comparison between Unknown and I4
			//IL_0068: 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_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)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			if (!IsListening())
			{
				return;
			}
			Event current = Event.current;
			if (current.isKey && (int)current.keyCode == 0)
			{
				return;
			}
			if ((int)current.keyCode == 27)
			{
				DeactivateKeyListen();
				return;
			}
			EventType type = current.type;
			if (((int)type == 0 || (int)type == 4 || (int)type == 6) ? true : false)
			{
				KeyCode val = current.keyCode;
				if (current.isMouse)
				{
					val = (KeyCode)(323 + current.button);
				}
				if (KeyUtils.IsModifier(val))
				{
					_caughtModifier = val;
				}
				else
				{
					_caughtKey = val;
				}
				UpdateKeyDisplay();
			}
			type = current.type;
			if (((int)type == 1 || type - 5 <= 1) ? true : false)
			{
				DeactivateKeyListen();
			}
		}
	}
	internal class ModuleButtonController : MonoBehaviour, IPointerClickHandler, IEventSystemHandler, IPointerEnterHandler, IPointerExitHandler, ISelectHandler, IDeselectHandler
	{
		public ThornClient.Core.Module? TargetModule;

		private Colorizer? _iconColorizer;

		private Colorizer? _textColorizer;

		private GameObject? _settingIcon;

		private void Start()
		{
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Expected O, but got Unknown
			if (TargetModule == null)
			{
				Plugin.Log.LogWarning((object)"[ModuleButtonController] TargetModule not assigned!");
				return;
			}
			GameObject obj = UIUtils.FindRecursive(((Component)this).gameObject, "Icon");
			Image val = ((obj != null) ? obj.GetComponent<Image>() : null);
			try
			{
				if ((Object)(object)val != (Object)null)
				{
					val.sprite = TargetModule.Icon;
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Failed to load icon for module '{TargetModule.Name}': {arg}");
			}
			GameObject obj2 = UIUtils.FindRecursive(((Component)this).gameObject, "Name");
			TextMeshProUGUI val2 = ((obj2 != null) ? obj2.GetComponent<TextMeshProUGUI>() : null);
			if (val2 != null)
			{
				((TMP_Text)val2).SetText(TargetModule.Name, true);
			}
			((UnityEvent)((Component)this).gameObject.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				TargetModule.Toggle();
			});
			_settingIcon = UIUtils.FindRecursive(((Component)this).gameObject, "ConfigButton/Icon");
			GameObject? settingIcon = _settingIcon;
			if (settingIcon != null)
			{
				settingIcon.SetActive(false);
			}
			GameObject obj3 = UIUtils.FindRecursive(((Component)this).gameObject, "ConfigButton");
			Button val3 = ((obj3 != null) ? obj3.GetComponent<Button>() : null);
			if ((Object)(object)val3 != (Object)null)
			{
				((UnityEvent)val3.onClick).AddListener((UnityAction)delegate
				{
					ClickGUI.NestConfigPanel(TargetModule);
				});
			}
			string name = TargetModule.GetType().Assembly.GetName().Name;
			((Component)this).gameObject.AddComponent<ClickGUITooltipHandler>().Text = TargetModule.Description + "<size=8>\n\n</size><size=10>[<color=#" + ColorUtility.ToHtmlStringRGB(ThornModule.AccentColor) + ">" + name + "</color>]</size>";
			UIUtils.FindRecursive(((Component)this).gameObject, "ConfigButton/Icon");
			_iconColorizer = ComponentExtensions.GetOrAddComponent<Colorizer>((Component)(object)val);
			_textColorizer = ComponentExtensions.GetOrAddComponent<Colorizer>((Component)(object)val2);
			TargetModule.OnToggleStateChanged += UpdateVisualState;
			UpdateVisualState(TargetModule.IsEnabled);
		}

		private void OnDestroy()
		{
			if (TargetModule != null)
			{
				TargetModule.OnToggleStateChanged -= UpdateVisualState;
			}
		}

		private void OnDisable()
		{
			GameObject? settingIcon = _settingIcon;
			if (settingIcon != null)
			{
				settingIcon.SetActive(false);
			}
		}

		private void UpdateVisualState(bool isEnabled)
		{
			if ((Object)(object)_iconColorizer != (Object)null)
			{
				_iconColorizer.Highlighted = isEnabled;
			}
			if ((Object)(object)_textColorizer != (Object)null)
			{
				_textColorizer.Highlighted = isEnabled;
			}
		}

		public void OnPointerClick(PointerEventData eventData)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)eventData.button == 1)
			{
				ClickGUI.NestConfigPanel(TargetModule);
				GameObject? settingIcon = _settingIcon;
				if (settingIcon != null)
				{
					settingIcon.SetActive(false);
				}
			}
		}

		public void OnPointerEnter(PointerEventData eventData)
		{
			GameObject? settingIcon = _settingIcon;
			if (settingIcon != null)
			{
				settingIcon.SetActive(true);
			}
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			GameObject? settingIcon = _settingIcon;
			if (settingIcon != null)
			{
				settingIcon.SetActive(false);
			}
		}

		public void OnSelect(BaseEventData eventData)
		{
			GameObject? settingIcon = _settingIcon;
			if (settingIcon != null)
			{
				settingIcon.SetActive(true);
			}
		}

		public void OnDeselect(BaseEventData eventData)
		{
			GameObject? settingIcon = _settingIcon;
			if (settingIcon != null)
			{
				settingIcon.SetActive(false);
			}
		}
	}
	internal class ModuleCategoryController : MonoBehaviour
	{
		private bool _doneSetup;

		public ModuleCategory Category;

		private static readonly Dictionary<ModuleCategory, string> _iconNameMap = new Dictionary<ModuleCategory, string>
		{
			{
				ModuleCategory.Utility,
				"compass"
			},
			{
				ModuleCategory.Render,
				"eye"
			},
			{
				ModuleCategory.Gameplay,
				"options"
			},
			{
				ModuleCategory.Misc,
				"shapes"
			},
			{
				ModuleCategory.Hud,
				"hud"
			}
		};

		private void Start()
		{
			SetupModules();
		}

		public void SetupModules()
		{
			if (_doneSetup)
			{
				return;
			}
			_doneSetup = true;
			GameObject val = UIUtils.FindRecursive(((Component)this).gameObject, "Scroll View/Viewport/Content/Modules");
			((Selectable)UIUtils.FindRecursive(((Component)this).gameObject, "Header/TitleButton").GetComponent<Button>()).interactable = false;
			Image component = UIUtils.FindRecursive(((Component)this).gameObject, "Header/TitleButton/TitleIcon").GetComponent<Image>();
			TextMeshProUGUI component2 = UIUtils.FindRecursive(((Component)this).gameObject, "Header/TitleName").GetComponent<TextMeshProUGUI>();
			component.sprite = AssetManager.Get<Sprite>(ClickGUI.BundleKey, _iconNameMap[Category]);
			((TMP_Text)component2).text = Category.ToString().ToUpper();
			GameObject obj = UIUtils.FindRecursive(((Component)this).gameObject, "Header");
			if (obj != null)
			{
				GameObjectExtensions.GetOrAddComponent<TitlebarDragHandler>(obj);
			}
			if ((Object)(object)AssetManager.Get<GameObject>(ClickGUI.BundleKey, "ModuleButton") == (Object)null)
			{
				Plugin.Log.LogError((object)"ModuleButtonPrefab is null, cannot populate modules");
				return;
			}
			foreach (ThornClient.Core.Module item in from m in ModuleManager.GetByCategory(Category)
				where !(m is SystemModule)
				select m)
			{
				GameObjectExtensions.GetOrAddComponent<ModuleButtonController>(Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "ModuleButton"), val.transform)).TargetModule = item;
			}
			UIUtils.UnfuckLayoutHack(((Component)this).gameObject);
		}
	}
	internal class ModuleSearchWindowController : MonoBehaviour
	{
		public int maxResults = 10;

		private bool _populated;

		private TMP_InputField? _input;

		private GameObject? _results;

		private Dictionary<string, GameObject> _allModules = new Dictionary<string, GameObject>();

		private Searchable[]? _searchables;

		[CompilerGenerated]
		private Predicate<ThornClient.Core.Module> <ModuleFilter>k__BackingField = (ThornClient.Core.Module _) => true;

		public Predicate<ThornClient.Core.Module> ModuleFilter
		{
			[CompilerGenerated]
			get
			{
				return <ModuleFilter>k__BackingField;
			}
			set
			{
				<ModuleFilter>k__BackingField = value;
				Repopulate();
			}
		}

		private void Awake()
		{
			_results = UIUtils.FindRecursive(((Component)this).gameObject, "Modules/Results");
		}

		private void Start()
		{
			GameObject val = UIUtils.FindRecursive(((Component)this).gameObject, "Modules/Input");
			if ((Object)(object)val != (Object)null)
			{
				_input = val.GetComponent<TMP_InputField>();
			}
			PopulateIfNeeded();
			if ((Object)(object)_input != (Object)null)
			{
				((UnityEvent<string>)(object)_input.onValueChanged).AddListener((UnityAction<string>)Query);
			}
			GameObject obj = UIUtils.FindRecursive(((Component)this).gameObject, "Header");
			if (obj != null)
			{
				GameObjectExtensions.GetOrAddComponent<TitlebarDragHandler>(obj);
			}
			Query("");
		}

		private void OnDestroy()
		{
			if ((Object)(object)_input != (Object)null)
			{
				((UnityEvent<string>)(object)_input.onValueChanged).RemoveListener((UnityAction<string>)Query);
			}
		}

		private void Repopulate()
		{
			_populated = false;
			foreach (GameObject value in _allModules.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
			}
			_allModules.Clear();
			_searchables = null;
			PopulateIfNeeded();
			Query(((Object)(object)_input != (Object)null) ? _input.text : "");
		}

		public void FocusSearch()
		{
			if ((Object)(object)_input != (Object)null)
			{
				EventSystem.current.SetSelectedGameObject(((Component)_input).gameObject, (BaseEventData)null);
				_input.ActivateInputField();
			}
		}

		private void PopulateIfNeeded()
		{
			if (_populated)
			{
				return;
			}
			_populated = true;
			List<ThornClient.Core.Module> list = ModuleManager.Items.Where((ThornClient.Core.Module m) => ModuleFilter(m)).ToList();
			foreach (ThornClient.Core.Module item in list)
			{
				GameObject obj = AssetManager.Get<GameObject>(ClickGUI.BundleKey, "ModuleButton");
				GameObject? results = _results;
				GameObject val = Object.Instantiate<GameObject>(obj, (results != null) ? results.transform : null);
				UIUtils.UnfuckLayoutHack(val);
				val.SetActive(false);
				GameObjectExtensions.GetOrAddComponent<ModuleButtonController>(val).TargetModule = item;
				try
				{
					_allModules.TryAdd(item.Name, val);
				}
				catch (Exception arg)
				{
					Plugin.Log.LogWarning((object)$"Failed to add module {item.Name} to search, are there two with the same name?\n{arg}");
				}
			}
			_searchables = ((IEnumerable<ThornClient.Core.Module>)list).Select((Func<ThornClient.Core.Module, Searchable>)((ThornClient.Core.Module module) => new Searchable
			{
				Primary = module.Name,
				Secondaries = new Dictionary<string, string>
				{
					{ "description", module.Description },
					{
						"tags",
						string.Join(" ", module.Tags ?? Array.Empty<string>())
					}
				}
			})).ToArray();
		}

		private void Query(string query)
		{
			if (_searchables == null)
			{
				return;
			}
			Searchable[] array = ((query.Length > 0) ? Search.Invoke(query, _searchables) : Array.Empty<Searchable>());
			foreach (GameObject value2 in _allModules.Values)
			{
				if (!((Object)(object)value2 == (Object)null))
				{
					UIUtils.UnfuckLayoutHack(value2);
					value2.SetActive(false);
				}
			}
			for (int i = 0; i < array.Length && i < maxResults; i++)
			{
				Searchable val = array[i];
				if (_allModules.TryGetValue(val.Primary, out GameObject value) && !((Object)(object)value == (Object)null))
				{
					value.SetActive(true);
					value.transform.SetAsLastSibling();
				}
			}
			if ((Object)(object)_results != (Object)null)
			{
				UIUtils.UnfuckLayoutHack(_results);
			}
			UIUtils.UnfuckLayoutHack(((Component)this).gameObject);
		}
	}
	internal abstract class NumberSettingController<T> : MonoBehaviour
	{
		public Setting<T>? TargetSetting;

		private TMP_InputField? _inputField;

		private ValueScrubController? _scrubController;

		private Slider? _slider;

		private string _lastString = string.Empty;

		private int _decimals = 1;

		private T _beforeScrub;

		private void Start()
		{
			GameObject obj = UIUtils.FindRecursive(((Component)this).gameObject, "MainField/Input");
			_inputField = ((obj != null) ? obj.GetComponent<TMP_InputField>() : null);
			if ((Object)(object)_inputField == (Object)null)
			{
				return;
			}
			ComponentExtensions.GetOrAddComponent<InputFocusGrab>((Component)(object)_inputField);
			((UnityEvent<string>)(object)_inputField.onSelect).AddListener((UnityAction<string>)SavePrevValue);
			((UnityEvent<string>)(object)_inputField.onEndEdit).AddListener((UnityAction<string>)SaveNewValue);
			if (TargetSetting == null)
			{
				return;
			}
			if (TargetSetting.Hints != null && TargetSetting.Hints.Range != null)
			{
				if (TargetSetting.Hints.Decimals.HasValue)
				{
					_decimals = TargetSetting.Hints.Decimals.Value;
				}
				Tuple<float, float> range = TargetSetting.Hints.Range;
				GameObject val = UIUtils.FindRecursive(((Component)this).gameObject, "Slider");
				if ((Object)(object)val != (Object)null)
				{
					val.SetActive(true);
					_slider = val.GetComponent<Slider>();
					_slider.minValue = Math.Min(range.Item1, range.Item2);
					_slider.maxValue = Math.Max(range.Item1, range.Item2);
					((UnityEvent<float>)(object)_slider.onValueChanged).AddListener((UnityAction<float>)delegate(float x)
					{
						SaveNewValue(Math.Round(x, _decimals).ToString());
					});
				}
			}
			else
			{
				_scrubController = GameObjectExtensions.GetOrAddComponent<ValueScrubController>(((Component)this).gameObject);
				_scrubController.OnScrubStart += SavePrevValue;
				_scrubController.OnValueScrub += UpdateScrub;
			}
			Setting<T>? targetSetting = TargetSetting;
			targetSetting.OnValueChanged = (Action<T>)Delegate.Combine(targetSetting.OnValueChanged, new Action<T>(UpdateFieldValue));
			UpdateFieldValue(TargetSetting.Value);
		}

		private void OnDestroy()
		{
			if (TargetSetting != null)
			{
				Setting<T>? targetSetting = TargetSetting;
				targetSetting.OnValueChanged = (Action<T>)Delegate.Remove(targetSetting.OnValueChanged, new Action<T>(UpdateFieldValue));
			}
			if (!((Object)(object)_inputField == (Object)null))
			{
				((UnityEvent<string>)(object)_inputField.onSelect).RemoveListener((UnityAction<string>)SavePrevValue);
				((UnityEvent<string>)(object)_inputField.onEndEdit).RemoveListener((UnityAction<string>)SaveNewValue);
				if ((Object)(object)_scrubController != (Object)null)
				{
					_scrubController.OnScrubStart -= SavePrevValue;
					_scrubController.OnValueScrub -= UpdateScrub;
				}
			}
		}

		private void SavePrevValue()
		{
			if (TargetSetting != null)
			{
				_beforeScrub = TargetSetting.Value;
			}
		}

		protected abstract void UpdateScrub(T baseValue, float valueDiff);

		private void UpdateScrub(float valueDiff)
		{
			UpdateScrub(_beforeScrub, valueDiff);
		}

		private void UpdateFieldValue(T value)
		{
			if ((Object)(object)_inputField == (Object)null)
			{
				return;
			}
			try
			{
				_inputField.text = value.ToString();
				if ((Object)(object)_slider != (Object)null && float.TryParse(value.ToString(), out var result))
				{
					_slider.value = result;
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogWarning((object)$"{typeof(T)} cannot be converted to string: {arg}");
			}
		}

		private void SavePrevValue(string str)
		{
			_lastString = str;
		}

		private void SaveNewValue(string str)
		{
			if (TargetSetting != null)
			{
				if (double.TryParse(str, out var result))
				{
					TargetSetting.Value = (T)Convert.ChangeType(result, typeof(T));
				}
				else
				{
					UpdateFieldValue(TargetSetting.Value);
				}
			}
		}
	}
	internal class SettingDescriptionController : MonoBehaviour
	{
		public IConfigurableElement TargetSetting;

		private void Start()
		{
			GameObject val = UIUtils.FindRecursive(((Component)this).gameObject, "Name", false);
			if ((Object)(object)val == (Object)null)
			{
				val = UIUtils.FindRecursive(((Component)this).gameObject, "TopRow/Name", false);
			}
			if ((Object)(object)val == (Object)null)
			{
				val = UIUtils.FindRecursive(((Component)this).gameObject, "MainField/Name");
			}
			if (!((Object)(object)val == (Object)null))
			{
				((TMP_Text)val.GetComponent<TextMeshProUGUI>()).text = TargetSetting.Name;
				GameObjectExtensions.GetOrAddComponent<ClickGUITooltipHandler>(((Component)this).gameObject).Text = TargetSetting.Description;
			}
		}
	}
	internal class SettingGroupWindowController : MonoBehaviour
	{
		private bool _doneSetup;

		public SettingGroup TargetGroup;

		private void Start()
		{
			SetupStuff();
		}

		public void SetupStuff()
		{
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Expected O, but got Unknown
			if (_doneSetup)
			{
				return;
			}
			_doneSetup = true;
			if (TargetGroup != null)
			{
				UIUtils.FindRecursive(((Component)this).gameObject, "Header/TitleButton/TitleIcon").SetActive(false);
				((TMP_Text)UIUtils.FindRecursive(((Component)this).gameObject, "Header/TitleName").GetComponent<TextMeshProUGUI>()).text = TargetGroup.Name;
				GameObject obj = UIUtils.FindRecursive(((Component)this).gameObject, "Header");
				if (obj != null)
				{
					obj.AddComponent<TitlebarDragHandler>();
				}
				GameObject obj2 = UIUtils.FindRecursive(((Component)this).gameObject, "Header/TitleButton");
				Button obj3 = ((obj2 != null) ? obj2.GetComponent<Button>() : null);
				((Selectable)UIUtils.FindRecursive(((Component)this).gameObject, "Header/TitleButton").GetComponent<Button>()).interactable = true;
				GameObject obj4 = UIUtils.FindRecursive(((Component)this).gameObject, "Header/TitleButton/BackIcon");
				if (obj4 != null)
				{
					obj4.SetActive(true);
				}
				((UnityEvent)obj3.onClick).AddListener((UnityAction)delegate
				{
					Object.Destroy((Object)(object)((Component)this).gameObject);
				});
				Transform transform = UIUtils.FindRecursive(((Component)this).gameObject, "Scroll View/Viewport/Content/Modules").transform;
				Populate(transform, TargetGroup.Elements);
				UIUtils.UnfuckLayoutHack(((Component)this).gameObject);
			}
		}

		private void Populate(Transform parent, IEnumerable<IConfigurableElement> elements)
		{
			foreach (IConfigurableElement element in elements)
			{
				GameObject val = null;
				if (element is Setting setting)
				{
					val = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "SettingRowWrapper"), parent);
					val.AddComponent<SettingRowController>().TargetSetting = setting;
					if (ConfigurableElementUICreators.SettingUICreators.TryGetValue(setting.Type, out Func<Setting, Transform, GameObject> value))
					{
						value(setting, val.transform).AddComponent<SettingDescriptionController>().TargetSetting = setting;
					}
				}
				else if (element is SettingGroup || element is ConfigButtonRow)
				{
					val = Object.Instantiate<GameObject>(AssetManager.Get<GameObject>(ClickGUI.BundleKey, "SettingRowWrapper"), parent);
					if (ConfigurableElementUICreators.MenuUICreators.TryGetValue(element.GetType(), out Func<IConfigurableElement, Transform, GameObject> value2))
					{
						value2(element, val.transform).AddComponent<SettingDescriptionController>().TargetSetting = element;
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					UIUtils.UnfuckLayoutHack(val);
					if (element.Hints?.Hidden == true)
					{
						val.SetActive(false);
					}
				}
			}
		}
	}
	internal class SettingRowController : MonoBehaviour
	{
		public Setting? TargetSetting;

		private GameObject? _resetButton;

		private Image? _resetButtonIconImage;

		private Button _resetButtonComp;

		private void Start()
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			if (TargetSetting != null)
			{
				_resetButton = UIUtils.FindRecursive(((Component)this).gameObject, "RevertButtonWrapper/RevertButton");
				_resetButtonIconImage = UIUtils.FindRecursive(_resetButton, "Icon").GetComponent<Image>();
				if (!((Object)(object)_resetButton == (Object)null))
				{
					_resetButtonComp = _resetButton.GetComponent<Button>();
					UpdateResetVisibility();
					((UnityEvent)_resetButtonComp.onClick).AddListener(new UnityAction(ResetSetting));
					TargetSetting.OnChanged += UpdateResetVisibility;
				}
			}
		}

		private void OnDestroy()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			if (TargetSetting != null)
			{
				TargetSetting.OnChanged -= UpdateResetVisibility;
			}
			if ((Object)(object)_resetButtonComp != (Object)null)
			{
				((UnityEvent)_resetButtonComp.onClick).RemoveListener(new UnityAction(ResetSetting));
			}
		}

		private void UpdateResetVisibility()
		{
			if (TargetSetting != null && !((Object)(object)_resetButton == (Object)null) && !((Object)(object)_resetButtonIconImage == (Object)null))
			{
				bool flag = !TargetSetting.IsDefault;
				_resetButtonIconImage.sprite = AssetManager.Get<Sprite>(ClickGUI.BundleKey, fl