Decompiled source of HtF ConfigMenu v1.0.0

BepInEx/plugins/HtF_ConfigMenu/HtF.ConfigMenu.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using HtF.Shared;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
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("HtF.ConfigMenu")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+76aa5112a8a5b0c9897d3f3557b28a045762e8aa")]
[assembly: AssemblyProduct("HtF.ConfigMenu")]
[assembly: AssemblyTitle("HtF.ConfigMenu")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace HtF.Shared
{
	public enum Language
	{
		Auto,
		Chinese,
		English
	}
	public static class Loc
	{
		private sealed class Entry
		{
			internal string NameZh;

			internal string NameEn;

			internal string DescZh;

			internal string DescEn;
		}

		private const string OwnerGuid = "htf.configmenu";

		private const string OwnerSection = "介面";

		private const string OwnerKey = "語言";

		private static readonly Dictionary<string, Entry> Entries = new Dictionary<string, Entry>(StringComparer.Ordinal);

		public static Func<string> LocalChoice;

		private static ConfigEntryBase _remote;

		private static string _remoteChoice;

		private static float _nextRemoteRead;

		public static bool IsEnglish { get; private set; }

		public static ConfigEntry<T> Bind<T>(ConfigFile file, string section, string key, T defaultValue, string nameEn, string descZh, string descEn = null, AcceptableValueBase range = null)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			Add(key, null, nameEn, descZh, descEn);
			return file.Bind<T>(section, key, defaultValue, new ConfigDescription(CfgDesc(key), range, Array.Empty<object>()));
		}

		public static void Section(string section, string nameEn)
		{
			Add(section, null, nameEn, null, null);
		}

		public static void EnumValue(object value, string nameZh, string nameEn)
		{
			if (value != null)
			{
				Add("enum." + value, nameZh, nameEn, null, null);
			}
		}

		public static void Add(string key, string nameZh, string nameEn, string descZh, string descEn)
		{
			if (!string.IsNullOrEmpty(key))
			{
				Entries[key] = new Entry
				{
					NameZh = nameZh,
					NameEn = nameEn,
					DescZh = descZh,
					DescEn = descEn
				};
			}
		}

		public static string Term(string key, bool english, bool wantDesc)
		{
			if (key == null || !Entries.TryGetValue(key, out var value))
			{
				return null;
			}
			if (wantDesc)
			{
				if (!english)
				{
					return value.DescZh;
				}
				return value.DescEn;
			}
			if (!english)
			{
				return value.NameZh;
			}
			return value.NameEn;
		}

		public static string CfgDesc(string key)
		{
			if (key == null || !Entries.TryGetValue(key, out var value) || value.DescZh == null)
			{
				return "";
			}
			if (value.DescEn != null)
			{
				return value.DescZh + "\n" + value.DescEn;
			}
			return value.DescZh;
		}

		public static void Resolve()
		{
			string text = ((LocalChoice != null) ? LocalChoice() : RemoteChoice());
			if (text == "English")
			{
				IsEnglish = true;
			}
			else if (text == "Chinese")
			{
				IsEnglish = false;
			}
			else
			{
				IsEnglish = !GameSpeaksChinese();
			}
		}

		private static string RemoteChoice()
		{
			if (Time.unscaledTime < _nextRemoteRead)
			{
				return _remoteChoice;
			}
			_nextRemoteRead = Time.unscaledTime + 0.5f;
			try
			{
				if (_remote == null)
				{
					if (!Chainloader.PluginInfos.TryGetValue("htf.configmenu", out var value))
					{
						return _remoteChoice = null;
					}
					if (value == null || (Object)(object)value.Instance == (Object)null || value.Instance.Config == null)
					{
						return _remoteChoice = null;
					}
					ConfigEntryBase[] configEntries = value.Instance.Config.GetConfigEntries();
					foreach (ConfigEntryBase val in configEntries)
					{
						if (val.Definition.Section == "介面" && val.Definition.Key == "語言")
						{
							_remote = val;
							break;
						}
					}
					if (_remote == null)
					{
						return _remoteChoice = null;
					}
				}
				_remoteChoice = _remote.BoxedValue?.ToString();
			}
			catch (Exception)
			{
				_remoteChoice = null;
			}
			return _remoteChoice;
		}

		private static bool GameSpeaksChinese()
		{
			try
			{
				int curLanguage = LocalizationManager.CurLanguage;
				return curLanguage == 2 || curLanguage == 3;
			}
			catch (Exception)
			{
				return false;
			}
		}

		public static string P(string zh, string en)
		{
			if (!IsEnglish)
			{
				return zh;
			}
			return en;
		}
	}
}
namespace HtF.ConfigMenu
{
	internal static class L
	{
		internal const string SecUi = "介面";

		internal const string SecButton = "選單按鈕";

		internal const string KeyLanguage = "語言";

		internal const string KeyToggle = "開關鍵";

		internal const string KeyScale = "縮放";

		internal const string KeyFont = "字型";

		internal const string KeyRaw = "顯示原始值";

		internal const string KeyPause = "暫停選單顯示按鈕";

		internal const string KeyMenu = "主選單顯示按鈕";

		internal const string KeyLabel = "按鈕文字";

		internal const string KeySlot = "按鈕位置";

		internal const string KeyDump = "診斷:印出按鈕分組";

		internal static string WindowTitle => Loc.P("模組設定", "Mod Settings");

		internal static string ButtonLabelDefault => Loc.P("模組設定", "Mod Settings");

		internal static string Search => Loc.P("搜尋", "Search");

		internal static string Rescan => Loc.P("重新掃描", "Rescan");

		internal static string Close => Loc.P("關閉", "Close");

		internal static string ResetAll => Loc.P("全部重設", "Reset All");

		internal static string SaveFile => Loc.P("寫入檔案", "Save File");

		internal static string NoPlugins => Loc.P("沒有找到任何有設定的插件", "No plugins with settings found");

		internal static string NoMatches => Loc.P("沒有符合的設定", "No settings match the search");

		internal static string NoneSelected => Loc.P("(無)", "(none)");

		internal static string On => Loc.P("開", "On");

		internal static string Off => Loc.P("關", "Off");

		internal static string PressAKey => Loc.P("按下按鍵…", "Press a key…");

		internal static void Register()
		{
			Loc.Section("介面", "Interface");
			Loc.Section("選單按鈕", "Menu Button");
			Loc.EnumValue(Language.Auto, "自動(跟隨遊戲)", "Auto (follow game)");
			Loc.EnumValue(Language.Chinese, "中文", "Chinese");
			Loc.EnumValue(Language.English, "英文", "English");
			Loc.EnumValue(ButtonSlot.AboveLast, "最後一顆的上面", "Above the last button");
			Loc.EnumValue(ButtonSlot.Bottom, "整欄最下面", "Bottom of the column");
			Loc.EnumValue(ButtonSlot.Top, "整欄最上面", "Top of the column");
		}
	}
	internal enum ButtonSlot
	{
		AboveLast,
		Bottom,
		Top
	}
	internal static class MenuButtons
	{
		private sealed class Column
		{
			internal Transform Parent;

			internal List<Button> Buttons;

			internal int LayoutRank;

			internal string Path;
		}

		private const string CloneName = "HtF_ConfigMenuButton";

		private static GameObject _pauseButton;

		private static GameObject _menuButton;

		private static float _nextTry;

		private static bool _dumped;

		private static string _appliedLabel;

		private static ButtonSlot _appliedSlot;

		private static FieldInfo _fPauseInstance;

		private static FieldInfo _fMainScreen;

		private static FieldInfo _fPauseHolder;

		private static bool _resolved;

		internal static void Tick()
		{
			if (Time.unscaledTime < _nextTry)
			{
				return;
			}
			_nextTry = Time.unscaledTime + 1f;
			try
			{
				if (Plugin.DumpMenus.Value && !_dumped)
				{
					Dump();
				}
				SyncSettings();
				if (Plugin.ShowPauseButton.Value)
				{
					if (!Object.op_Implicit((Object)(object)_pauseButton))
					{
						InjectPause();
					}
				}
				else
				{
					Remove(ref _pauseButton);
				}
				if (Plugin.ShowMenuButton.Value)
				{
					if (!Object.op_Implicit((Object)(object)_menuButton))
					{
						InjectMainMenu();
					}
				}
				else
				{
					Remove(ref _menuButton);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("插入選單按鈕失敗:" + ex.Message));
			}
		}

		private static void SyncSettings()
		{
			string text = Label();
			if (text != _appliedLabel)
			{
				_appliedLabel = text;
				if (Object.op_Implicit((Object)(object)_pauseButton))
				{
					SetLabel(_pauseButton, text);
				}
				if (Object.op_Implicit((Object)(object)_menuButton))
				{
					SetLabel(_menuButton, text);
				}
			}
			ButtonSlot value = Plugin.ButtonPosition.Value;
			if (value != _appliedSlot)
			{
				_appliedSlot = value;
				Remove(ref _pauseButton);
				Remove(ref _menuButton);
			}
		}

		private static string Label()
		{
			string text = ((Plugin.ButtonLabel != null) ? Plugin.ButtonLabel.Value : null);
			if (!string.IsNullOrEmpty(text) && text.Trim().Length != 0)
			{
				return text;
			}
			return L.ButtonLabelDefault;
		}

		private static void Remove(ref GameObject clone)
		{
			if (Object.op_Implicit((Object)(object)clone))
			{
				Object.Destroy((Object)(object)clone);
			}
			clone = null;
		}

		private static void InjectPause()
		{
			GameObject val = FieldObject(_fMainScreen);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			Column column = BiggestColumn(val.GetComponentsInChildren<Button>(true));
			if (column != null)
			{
				_pauseButton = Clone(column, Label());
				if (Object.op_Implicit((Object)(object)_pauseButton))
				{
					Plugin.Log.LogInfo((object)("已在暫停選單加入按鈕(欄位 " + column.Path + "," + column.Buttons.Count + " 顆)。"));
				}
			}
		}

		private static void InjectMainMenu()
		{
			if (!MainMenuManager.IsInMenu)
			{
				return;
			}
			GameObject val = FieldObject(_fPauseHolder);
			List<Button> list = new List<Button>();
			Button[] array = Object.FindObjectsByType<Button>((FindObjectsInactive)0, (FindObjectsSortMode)0);
			foreach (Button val2 in array)
			{
				if (Object.op_Implicit((Object)(object)val2) && ((Component)val2).gameObject.activeInHierarchy && (!Object.op_Implicit((Object)(object)val) || !((Component)val2).transform.IsChildOf(val.transform)) && IsVisible(((Component)val2).transform))
				{
					list.Add(val2);
				}
			}
			Column column = BiggestColumn(list.ToArray());
			if (column != null)
			{
				_menuButton = Clone(column, Label());
				if (Object.op_Implicit((Object)(object)_menuButton))
				{
					Plugin.Log.LogInfo((object)("已在主選單加入按鈕(欄位 " + column.Path + "," + column.Buttons.Count + " 顆)。"));
				}
			}
		}

		private static bool IsVisible(Transform t)
		{
			Transform val = t;
			int num = 0;
			while (Object.op_Implicit((Object)(object)val) && num++ < 12)
			{
				CanvasGroup component = ((Component)val).GetComponent<CanvasGroup>();
				if (Object.op_Implicit((Object)(object)component) && (component.alpha < 0.1f || !component.blocksRaycasts))
				{
					return false;
				}
				val = val.parent;
			}
			return true;
		}

		private static Column BiggestColumn(Button[] buttons)
		{
			Dictionary<Transform, List<Button>> dictionary = new Dictionary<Transform, List<Button>>();
			foreach (Button val in buttons)
			{
				if (!Object.op_Implicit((Object)(object)val) || ((Object)((Component)val).gameObject).name == "HtF_ConfigMenuButton")
				{
					continue;
				}
				Transform parent = ((Component)val).transform.parent;
				if (Object.op_Implicit((Object)(object)parent))
				{
					if (!dictionary.TryGetValue(parent, out var value))
					{
						value = (dictionary[parent] = new List<Button>());
					}
					value.Add(val);
				}
			}
			Column column = null;
			foreach (KeyValuePair<Transform, List<Button>> item in dictionary)
			{
				if (item.Value.Count >= 2)
				{
					item.Value.Sort(CompareBySibling);
					Column column2 = new Column
					{
						Parent = item.Key,
						Buttons = item.Value,
						LayoutRank = LayoutRank(item.Key),
						Path = Path(item.Key)
					};
					if (Better(column2, column))
					{
						column = column2;
					}
				}
			}
			return column;
		}

		private static int CompareBySibling(Button a, Button b)
		{
			return ((Component)a).transform.GetSiblingIndex().CompareTo(((Component)b).transform.GetSiblingIndex());
		}

		private static int LayoutRank(Transform parent)
		{
			if (Object.op_Implicit((Object)(object)((Component)parent).GetComponent<VerticalLayoutGroup>()))
			{
				return 2;
			}
			if (Object.op_Implicit((Object)(object)((Component)parent).GetComponent<LayoutGroup>()))
			{
				return 1;
			}
			return 0;
		}

		private static bool Better(Column a, Column b)
		{
			if (b == null)
			{
				return true;
			}
			if (a.LayoutRank != b.LayoutRank)
			{
				return a.LayoutRank > b.LayoutRank;
			}
			if (a.Buttons.Count != b.Buttons.Count)
			{
				return a.Buttons.Count > b.Buttons.Count;
			}
			int num = string.CompareOrdinal(a.Path, b.Path);
			if (num != 0)
			{
				return num < 0;
			}
			return a.Parent.GetSiblingIndex() < b.Parent.GetSiblingIndex();
		}

		private static GameObject Clone(Column column, string label)
		{
			//IL_0054: 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_0085: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			Button val = column.Buttons[column.Buttons.Count - 1];
			int siblingIndex = SlotIndex(column);
			GameObject obj = Object.Instantiate<GameObject>(((Component)val).gameObject, column.Parent);
			((Object)obj).name = "HtF_ConfigMenuButton";
			obj.transform.SetSiblingIndex(siblingIndex);
			obj.transform.localScale = ((Component)val).transform.localScale;
			StripLocalization(obj);
			SetLabel(obj, label);
			Button component = obj.GetComponent<Button>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.onClick = new ButtonClickedEvent();
				((UnityEvent)component.onClick).AddListener(new UnityAction(SettingsWindow.Toggle));
				((Selectable)component).interactable = true;
			}
			obj.SetActive(true);
			_appliedLabel = label;
			_appliedSlot = Plugin.ButtonPosition.Value;
			return obj;
		}

		private static int SlotIndex(Column column)
		{
			List<Button> buttons = column.Buttons;
			return Plugin.ButtonPosition.Value switch
			{
				ButtonSlot.Top => ((Component)buttons[0]).transform.GetSiblingIndex(), 
				ButtonSlot.Bottom => ((Component)buttons[buttons.Count - 1]).transform.GetSiblingIndex() + 1, 
				_ => ((Component)buttons[buttons.Count - 1]).transform.GetSiblingIndex(), 
			};
		}

		private static void StripLocalization(GameObject root)
		{
			MonoBehaviour[] componentsInChildren = root.GetComponentsInChildren<MonoBehaviour>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)componentsInChildren[i]) && ((object)componentsInChildren[i]).GetType().Name.IndexOf("Localize", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					Object.Destroy((Object)(object)componentsInChildren[i]);
				}
			}
		}

		private static void SetLabel(GameObject root, string label)
		{
			TMP_Text[] componentsInChildren = root.GetComponentsInChildren<TMP_Text>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)componentsInChildren[i]))
				{
					componentsInChildren[i].text = label;
				}
			}
			Text[] componentsInChildren2 = root.GetComponentsInChildren<Text>(true);
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				if (Object.op_Implicit((Object)(object)componentsInChildren2[j]))
				{
					componentsInChildren2[j].text = label;
				}
			}
		}

		private static void Dump()
		{
			_dumped = true;
			Button[] array = Object.FindObjectsByType<Button>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			Dictionary<Transform, int> dictionary = new Dictionary<Transform, int>();
			for (int i = 0; i < array.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)array[i]) && Object.op_Implicit((Object)(object)((Component)array[i]).transform.parent))
				{
					Transform parent = ((Component)array[i]).transform.parent;
					dictionary.TryGetValue(parent, out var value);
					dictionary[parent] = value + 1;
				}
			}
			Plugin.Log.LogInfo((object)"=== 場上按鈕分組(parent = 數量, layout 分級)===");
			foreach (KeyValuePair<Transform, int> item in dictionary)
			{
				Plugin.Log.LogInfo((object)("  " + Path(item.Key) + " = " + item.Value + ", layout " + LayoutRank(item.Key) + (((Component)item.Key).gameObject.activeInHierarchy ? "  [顯示中]" : "")));
			}
		}

		private static string Path(Transform t)
		{
			string text = ((Object)t).name;
			Transform parent = t.parent;
			int num = 0;
			while (Object.op_Implicit((Object)(object)parent) && num++ < 6)
			{
				text = ((Object)parent).name + "/" + text;
				parent = parent.parent;
			}
			return text;
		}

		private static GameObject FieldObject(FieldInfo field)
		{
			Resolve();
			if (_fPauseInstance == null || field == null)
			{
				return null;
			}
			object value = _fPauseInstance.GetValue(null);
			if (value == null || value.Equals(null))
			{
				return null;
			}
			object? value2 = field.GetValue(value);
			return (GameObject)((value2 is GameObject) ? value2 : null);
		}

		private static void Resolve()
		{
			if (!_resolved)
			{
				_resolved = true;
				_fPauseInstance = AccessTools.Field(typeof(PauseManager), "_instance");
				_fMainScreen = AccessTools.Field(typeof(PauseManager), "_mainScreen");
				_fPauseHolder = AccessTools.Field(typeof(PauseManager), "_pauseHolder");
				if (_fPauseInstance == null || _fMainScreen == null)
				{
					Plugin.Log.LogWarning((object)"PauseManager 的欄位對不上,暫停選單按鈕不會出現。");
				}
			}
		}
	}
	[BepInPlugin("htf.configmenu", "HtF Config Menu", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "htf.configmenu";

		private const string LegacyButtonLabel = "模組設定";

		internal static Plugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<Language> LanguageSetting;

		internal static ConfigEntry<KeyboardShortcut> ToggleKey;

		internal static ConfigEntry<float> UiScale;

		internal static ConfigEntry<string> FontName;

		internal static ConfigEntry<bool> ShowAdvanced;

		internal static ConfigEntry<bool> ShowPauseButton;

		internal static ConfigEntry<bool> ShowMenuButton;

		internal static ConfigEntry<bool> DumpMenus;

		internal static ConfigEntry<string> ButtonLabel;

		internal static ConfigEntry<ButtonSlot> ButtonPosition;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Expected O, but got Unknown
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			L.Register();
			LanguageSetting = Loc.Bind(((BaseUnityPlugin)this).Config, "介面", "語言", Language.Auto, "Language", "這個頁面和選單按鈕的語言。自動 = 跟著遊戲語系走(簡體/繁體以外都當英文)。\n其他 HtF mod 也會跟著這一個設定走。", "Language of this window and of the injected menu button. Auto follows the language the game itself is set to.\nThe other HtF mods follow this one setting too.");
			ToggleKey = Loc.Bind<KeyboardShortcut>(((BaseUnityPlugin)this).Config, "介面", "開關鍵", new KeyboardShortcut((KeyCode)290, Array.Empty<KeyCode>()), "Toggle Key", "開關設定頁面的按鍵。", "Key that opens and closes this window.");
			UiScale = Loc.Bind(((BaseUnityPlugin)this).Config, "介面", "縮放", 1f, "UI Scale", "視窗縮放倍率。", "Scale factor of the window.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.6f, 2f));
			FontName = Loc.Bind(((BaseUnityPlugin)this).Config, "介面", "字型", "Microsoft JhengHei UI", "Font", "系統字型名稱。留空 = 用 Unity 內建字型(中文可能變方塊)。", "System font name. Leave empty to use the built-in Unity font (CJK text may render as boxes).");
			ShowAdvanced = Loc.Bind(((BaseUnityPlugin)this).Config, "介面", "顯示原始值", defaultValue: false, "Show Raw Values", "在每個設定旁邊顯示它寫進 .cfg 的實際字串,除錯用。", "Show the exact string each setting writes into its .cfg file. For debugging.");
			ShowPauseButton = Loc.Bind(((BaseUnityPlugin)this).Config, "選單按鈕", "暫停選單顯示按鈕", defaultValue: true, "Show In Pause Menu", "在 ESC 選單插一顆「模組設定」按鈕。", "Add a mod settings button to the ESC pause menu.");
			ShowMenuButton = Loc.Bind(((BaseUnityPlugin)this).Config, "選單按鈕", "主選單顯示按鈕", defaultValue: true, "Show In Main Menu", "在主畫面插一顆「模組設定」按鈕。", "Add a mod settings button to the main menu.");
			ButtonLabel = Loc.Bind(((BaseUnityPlugin)this).Config, "選單按鈕", "按鈕文字", "", "Button Label", "插進選單那顆按鈕上顯示的文字。留空 = 跟著上面的語言設定自動切換。(舊版的預設值「模組設定」也算留空,見下面的說明。)", "Text shown on the injected menu button. Leave it empty to follow the language setting above. (The old default, 模組設定, counts as empty too.)");
			MigrateButtonLabel();
			ButtonPosition = Loc.Bind(((BaseUnityPlugin)this).Config, "選單按鈕", "按鈕位置", ButtonSlot.AboveLast, "Button Position", "按鈕插在那一欄的哪個位置。", "Where in the menu column the button is inserted.");
			DumpMenus = Loc.Bind(((BaseUnityPlugin)this).Config, "選單按鈕", "診斷:印出按鈕分組", defaultValue: false, "Diagnostics: Dump Button Groups", "把場上所有按鈕依父物件分組印進 BepInEx log。遊戲改版導致按鈕插不進去時,打開這個看實際結構。", "Dump every button in the scene, grouped by parent, into the BepInEx log. Turn this on if a game update breaks the injection.");
			Loc.LocalChoice = () => LanguageSetting.Value.ToString();
			Loc.Resolve();
			_harmony = new Harmony("htf.configmenu");
			_harmony.PatchAll(typeof(Patches));
			Log.LogInfo((object)("Config Menu 已載入,按 " + ((object)ToggleKey.Value/*cast due to .constrained prefix*/).ToString() + " 開啟。"));
		}

		private static void MigrateButtonLabel()
		{
			if (!(ButtonLabel.Value != "模組設定"))
			{
				ButtonLabel.Value = "";
				Log.LogInfo((object)"「按鈕文字」原本是舊版的預設值「模組設定」,已改成留空=跟著語言自動切換。要固定文字的話自己填一個就好。");
			}
		}

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

		private void Update()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			Loc.Resolve();
			KeyboardShortcut value = ToggleKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				SettingsWindow.Toggle();
			}
			SettingsWindow.Tick();
			MenuButtons.Tick();
		}

		private void OnGUI()
		{
			SettingsWindow.Draw();
		}
	}
	[HarmonyPatch]
	internal static class Patches
	{
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		private static void BlockInputs_Postfix(Player __instance, ref bool __result)
		{
			if (SettingsWindow.Visible && (Object)(object)__instance == (Object)(object)Player.LocalPlayer)
			{
				__result = true;
			}
		}
	}
	internal sealed class PluginBlock
	{
		public string Name;

		public string Guid;

		public string Version;

		public ConfigFile File;

		public ConfigEntryBase[] Entries;

		public Func<string, bool, bool, string> Terms;

		public string Label(string raw)
		{
			if (Terms == null || string.IsNullOrEmpty(raw))
			{
				return raw;
			}
			return Terms(raw, Loc.IsEnglish, arg3: false) ?? raw;
		}

		public string Desc(string raw, string fallback)
		{
			if (Terms == null || string.IsNullOrEmpty(raw))
			{
				return fallback;
			}
			return Terms(raw, Loc.IsEnglish, arg3: true) ?? fallback;
		}

		public string EnumText(object value)
		{
			if (value == null)
			{
				return "";
			}
			string text = value.ToString();
			if (Terms == null)
			{
				return text;
			}
			return Terms("enum." + text, Loc.IsEnglish, arg3: false) ?? text;
		}
	}
	internal static class TermProvider
	{
		private static readonly Dictionary<Assembly, Func<string, bool, bool, string>> Cache = new Dictionary<Assembly, Func<string, bool, bool, string>>();

		internal static Func<string, bool, bool, string> For(Assembly asm)
		{
			if (asm == null)
			{
				return null;
			}
			if (Cache.TryGetValue(asm, out var value))
			{
				return value;
			}
			try
			{
				Type type = asm.GetType("HtF.Shared.Loc", throwOnError: false);
				MethodInfo methodInfo = ((type == null) ? null : type.GetMethod("Term", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[3]
				{
					typeof(string),
					typeof(bool),
					typeof(bool)
				}, null));
				if (methodInfo != null && methodInfo.ReturnType == typeof(string))
				{
					value = (Func<string, bool, bool, string>)Delegate.CreateDelegate(typeof(Func<string, bool, bool, string>), methodInfo);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("讀取 " + asm.GetName().Name + " 的詞條表失敗:" + ex.Message));
				value = null;
			}
			Cache[asm] = value;
			return value;
		}
	}
	internal static class SettingsWindow
	{
		private const int WindowId = 790294;

		internal static bool Visible;

		private static Rect _rect = new Rect(90f, 60f, 960f, 660f);

		private static int _plugin;

		private static Vector2 _listScroll;

		private static Vector2 _bodyScroll;

		private static string _search = "";

		private static string _searchApplied = "";

		private static Font _font;

		private static bool _fontTried;

		private static readonly List<Action> Pending = new List<Action>();

		private static List<PluginBlock> _blocks;

		private static readonly Dictionary<ConfigEntryBase, string> Buffers = new Dictionary<ConfigEntryBase, string>();

		private static readonly Dictionary<ConfigEntryBase, float> Sliders = new Dictionary<ConfigEntryBase, float>();

		private static ConfigEntryBase _capturing;

		internal static void Toggle()
		{
			Visible = !Visible;
			_capturing = null;
			SetMouse(Visible);
			if (Visible)
			{
				Refresh();
			}
		}

		internal static void Tick()
		{
			if (Visible)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}

		private static void SetMouse(bool unlock)
		{
			try
			{
				PlayerCamera.ToggleMouse(unlock);
			}
			catch (Exception)
			{
			}
			if (unlock)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}

		private static void Defer(Action a)
		{
			Pending.Add(a);
		}

		internal static void Refresh()
		{
			List<PluginBlock> list = new List<PluginBlock>();
			try
			{
				foreach (PluginInfo value in Chainloader.PluginInfos.Values)
				{
					if (value != null && !((Object)(object)value.Instance == (Object)null) && value.Instance.Config != null)
					{
						ConfigEntryBase[] configEntries = value.Instance.Config.GetConfigEntries();
						if (configEntries != null && configEntries.Length != 0)
						{
							list.Add(new PluginBlock
							{
								Name = ((value.Metadata != null) ? value.Metadata.Name : ((object)value.Instance).GetType().Name),
								Guid = ((value.Metadata != null) ? value.Metadata.GUID : "?"),
								Version = ((value.Metadata != null && value.Metadata.Version != null) ? value.Metadata.Version.ToString() : ""),
								File = value.Instance.Config,
								Entries = configEntries,
								Terms = TermProvider.For(((object)value.Instance).GetType().Assembly)
							});
						}
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("列舉插件設定失敗:" + ex));
			}
			list.Sort((PluginBlock a, PluginBlock b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase));
			_blocks = list;
			if (_plugin >= _blocks.Count)
			{
				_plugin = 0;
			}
		}

		internal static void Draw()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Invalid comparison between Unknown and I4
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Expected O, but got Unknown
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			if (!Visible)
			{
				return;
			}
			GUI.depth = -1000;
			EnsureFont();
			Theme.Build(_font);
			if ((int)Event.current.type == 8)
			{
				if (Pending.Count > 0)
				{
					Action[] array = Pending.ToArray();
					Pending.Clear();
					for (int i = 0; i < array.Length; i++)
					{
						try
						{
							array[i]();
						}
						catch (Exception ex)
						{
							Plugin.Log.LogError((object)("延後動作失敗:" + ex));
						}
					}
				}
				if (_blocks == null)
				{
					Refresh();
				}
				_searchApplied = _search ?? "";
			}
			if (_capturing != null)
			{
				CaptureKey();
			}
			GUISkin skin = GUI.skin;
			Matrix4x4 matrix = GUI.matrix;
			GUI.skin = Theme.Skin;
			float num = ((Plugin.UiScale != null) ? Plugin.UiScale.Value : 1f);
			GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(num, num, 1f));
			_rect = GUILayout.Window(790294, _rect, new WindowFunction(DrawWindow), L.WindowTitle, Array.Empty<GUILayoutOption>());
			GUI.matrix = matrix;
			GUI.skin = skin;
		}

		private static void EnsureFont()
		{
			if (_fontTried)
			{
				return;
			}
			_fontTried = true;
			string text = ((Plugin.FontName != null) ? Plugin.FontName.Value : "");
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			try
			{
				_font = Font.CreateDynamicFontFromOSFont(text, 13);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("載入字型 " + text + " 失敗:" + ex.Message));
			}
		}

		private static void DrawWindow(int id)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			DrawHeader();
			Theme.Separator();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			DrawPluginList();
			GUILayout.Space(10f);
			DrawBody();
			GUILayout.EndHorizontal();
			GUI.DragWindow(new Rect(0f, 0f, 100000f, 26f));
		}

		private static void DrawHeader()
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(L.Search, Theme.ArgLabel, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(52f) });
			GUILayout.Space(4f);
			_search = GUILayout.TextField(_search ?? "", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(260f) });
			GUILayout.FlexibleSpace();
			if (GUILayout.Button(L.Rescan, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) }))
			{
				Defer(Refresh);
			}
			GUILayout.Space(6f);
			if (GUILayout.Button(L.Close, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(66f) }))
			{
				Defer(Toggle);
			}
			GUILayout.EndHorizontal();
		}

		private static void DrawPluginList()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(190f) });
			_listScroll = GUILayout.BeginScrollView(_listScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(Mathf.Max(240f, ((Rect)(ref _rect)).height - 96f)) });
			if (_blocks != null)
			{
				for (int i = 0; i < _blocks.Count; i++)
				{
					bool flag = _plugin == i;
					if (GUILayout.Toggle(flag, _blocks[i].Name, Theme.Tab, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }) && !flag)
					{
						int pick = i;
						Defer(delegate
						{
							//IL_000b: Unknown result type (might be due to invalid IL or missing references)
							//IL_0010: Unknown result type (might be due to invalid IL or missing references)
							_plugin = pick;
							_bodyScroll = Vector2.zero;
						});
					}
				}
				if (_blocks.Count == 0)
				{
					GUILayout.Label(L.NoPlugins, Theme.DimLabel, Array.Empty<GUILayoutOption>());
				}
			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
		}

		private static void DrawBody()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			PluginBlock pluginBlock = ((_blocks != null && _plugin < _blocks.Count) ? _blocks[_plugin] : null);
			if (pluginBlock == null)
			{
				GUILayout.Label(L.NoneSelected, Theme.DimLabel, Array.Empty<GUILayoutOption>());
				GUILayout.EndVertical();
				return;
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			Color contentColor = GUI.contentColor;
			GUI.contentColor = Theme.Accent;
			GUILayout.Label(pluginBlock.Name + ((pluginBlock.Version.Length > 0) ? ("  v" + pluginBlock.Version) : ""), Theme.Title, Array.Empty<GUILayoutOption>());
			GUI.contentColor = contentColor;
			GUILayout.FlexibleSpace();
			if (GUILayout.Button(L.ResetAll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(96f) }))
			{
				PluginBlock b = pluginBlock;
				Defer(delegate
				{
					ResetAll(b);
				});
			}
			GUILayout.Space(6f);
			if (GUILayout.Button(L.SaveFile, Theme.Run, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(96f) }))
			{
				PluginBlock b2 = pluginBlock;
				Defer(delegate
				{
					try
					{
						b2.File.Save();
						Plugin.Log.LogInfo((object)("已寫入 " + b2.File.ConfigFilePath));
					}
					catch (Exception ex)
					{
						Plugin.Log.LogError((object)ex);
					}
				});
			}
			GUILayout.EndHorizontal();
			GUILayout.Label(pluginBlock.Guid, Theme.DimLabel, Array.Empty<GUILayoutOption>());
			_bodyScroll = GUILayout.BeginScrollView(_bodyScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(Mathf.Max(200f, ((Rect)(ref _rect)).height - 150f)) });
			string text = (_searchApplied ?? "").Trim();
			string text2 = null;
			int num = 0;
			for (int num2 = 0; num2 < pluginBlock.Entries.Length; num2++)
			{
				ConfigEntryBase val = pluginBlock.Entries[num2];
				if (text.Length <= 0 || Matches(pluginBlock, val, text))
				{
					if (val.Definition.Section != text2)
					{
						text2 = val.Definition.Section;
						GUILayout.Space(6f);
						Color contentColor2 = GUI.contentColor;
						GUI.contentColor = Theme.Accent;
						GUILayout.Label("— " + pluginBlock.Label(text2) + " —", Theme.Head, Array.Empty<GUILayoutOption>());
						GUI.contentColor = contentColor2;
					}
					DrawEntry(pluginBlock, val);
					num++;
				}
			}
			if (num == 0)
			{
				GUILayout.Label(L.NoMatches, Theme.DimLabel, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
		}

		private static bool Matches(PluginBlock block, ConfigEntryBase e, string needle)
		{
			if (Has(e.Definition.Key, needle))
			{
				return true;
			}
			if (Has(e.Definition.Section, needle))
			{
				return true;
			}
			if (Has(block.Label(e.Definition.Key), needle))
			{
				return true;
			}
			if (Has(block.Label(e.Definition.Section), needle))
			{
				return true;
			}
			if (!Has((e.Description != null) ? e.Description.Description : null, needle))
			{
				return Has(block.Desc(e.Definition.Key, null), needle);
			}
			return true;
		}

		private static bool Has(string haystack, string needle)
		{
			if (!string.IsNullOrEmpty(haystack))
			{
				return haystack.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		private static void DrawEntry(PluginBlock block, ConfigEntryBase e)
		{
			GUILayout.BeginVertical(Theme.CardBox, Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			GUILayout.Label(block.Label(e.Definition.Key), Theme.Head, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(240f) });
			GUILayout.Space(8f);
			DrawWidget(block, e);
			GUILayout.FlexibleSpace();
			GUI.enabled = e.BoxedValue == null || !e.BoxedValue.Equals(e.DefaultValue);
			if (GUILayout.Button("↺", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(28f) }))
			{
				ConfigEntryBase entry = e;
				Defer(delegate
				{
					Reset(entry);
				});
			}
			GUI.enabled = true;
			GUILayout.EndHorizontal();
			string text = block.Desc(e.Definition.Key, (e.Description != null) ? e.Description.Description : "");
			if (!string.IsNullOrEmpty(text))
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Space(10f);
				GUILayout.Label(text, Theme.DimLabel, Array.Empty<GUILayoutOption>());
				GUILayout.EndHorizontal();
			}
			if (Plugin.ShowAdvanced.Value)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Space(10f);
				string text2;
				try
				{
					text2 = e.GetSerializedValue();
				}
				catch (Exception)
				{
					text2 = "?";
				}
				GUILayout.Label(e.SettingType.Name + " = " + text2, Theme.Mono, Array.Empty<GUILayoutOption>());
				GUILayout.EndHorizontal();
			}
			GUILayout.EndVertical();
		}

		private static void DrawWidget(PluginBlock block, ConfigEntryBase e)
		{
			Type settingType = e.SettingType;
			if (settingType == typeof(bool))
			{
				bool flag = (bool)e.BoxedValue;
				bool flag2 = GUILayout.Toggle(flag, flag ? L.On : L.Off, Theme.Pill, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(56f) });
				if (flag2 != flag)
				{
					ConfigEntryBase entry = e;
					bool v = flag2;
					Defer(delegate
					{
						Set(entry, v);
					});
				}
				return;
			}
			if (settingType == typeof(KeyboardShortcut))
			{
				if (GUILayout.Button((_capturing == e) ? L.PressAKey : e.BoxedValue.ToString(), Theme.Pill, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) }))
				{
					ConfigEntryBase entry2 = e;
					Defer(delegate
					{
						_capturing = ((_capturing == entry2) ? null : entry2);
					});
				}
				return;
			}
			if (settingType.IsEnum)
			{
				Array values = Enum.GetValues(settingType);
				int num = Array.IndexOf(values, e.BoxedValue);
				ConfigEntryBase ent = e;
				if (GUILayout.Button("◀", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(26f) }) && values.Length > 0)
				{
					object v2 = values.GetValue(((num - 1) % values.Length + values.Length) % values.Length);
					Defer(delegate
					{
						Set(ent, v2);
					});
				}
				GUILayout.Label(block.EnumText(e.BoxedValue), Theme.Label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(180f) });
				if (GUILayout.Button("▶", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(26f) }) && values.Length > 0)
				{
					object v3 = values.GetValue(((num + 1) % values.Length + values.Length) % values.Length);
					Defer(delegate
					{
						Set(ent, v3);
					});
				}
				return;
			}
			if (IsNumeric(settingType) && TryRange(e, out var min, out var max))
			{
				float num2 = Convert.ToSingle(e.BoxedValue, CultureInfo.InvariantCulture);
				if (!Sliders.TryGetValue(e, out var value))
				{
					value = num2;
				}
				float num3 = GUILayout.HorizontalSlider(value, min, max, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) });
				if (settingType == typeof(int) || settingType == typeof(long) || settingType == typeof(byte))
				{
					num3 = Mathf.Round(num3);
				}
				Sliders[e] = num3;
				GUILayout.Space(8f);
				GUILayout.Label(Format(num3, settingType), Theme.Label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) });
				if (!Input.GetMouseButton(0) && Math.Abs(num3 - num2) > 0.0001f)
				{
					ConfigEntryBase entry3 = e;
					float v4 = num3;
					Defer(delegate
					{
						Set(entry3, Convert.ChangeType(v4, entry3.SettingType, CultureInfo.InvariantCulture));
						Sliders.Remove(entry3);
					});
				}
				return;
			}
			if (!Buffers.TryGetValue(e, out var value2))
			{
				try
				{
					value2 = e.GetSerializedValue();
				}
				catch (Exception)
				{
					value2 = "";
				}
				value2 = value2.Trim('"');
			}
			string text = GUILayout.TextField(value2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(240f) });
			if (text != value2)
			{
				Buffers[e] = text;
				TryCommitText(e, text);
			}
		}

		private static void TryCommitText(ConfigEntryBase e, string text)
		{
			Type settingType = e.SettingType;
			try
			{
				if (settingType == typeof(string))
				{
					e.BoxedValue = text;
				}
				else if (IsNumeric(settingType))
				{
					if (double.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
					{
						object obj = Convert.ChangeType(result, settingType, CultureInfo.InvariantCulture);
						if (e.Description != null && e.Description.AcceptableValues != null)
						{
							obj = e.Description.AcceptableValues.Clamp(obj);
						}
						e.BoxedValue = obj;
					}
				}
				else
				{
					e.SetSerializedValue(text);
				}
			}
			catch (Exception)
			{
			}
		}

		private static void Set(ConfigEntryBase e, object value)
		{
			try
			{
				if (e.Description != null && e.Description.AcceptableValues != null)
				{
					value = e.Description.AcceptableValues.Clamp(value);
				}
				e.BoxedValue = value;
				Buffers.Remove(e);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("設定 " + e.Definition.Key + " 失敗:" + ex.Message));
			}
		}

		private static void Reset(ConfigEntryBase e)
		{
			try
			{
				e.BoxedValue = e.DefaultValue;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)ex.Message);
			}
			Buffers.Remove(e);
			Sliders.Remove(e);
		}

		private static void ResetAll(PluginBlock block)
		{
			for (int i = 0; i < block.Entries.Length; i++)
			{
				Reset(block.Entries[i]);
			}
			Plugin.Log.LogInfo((object)(block.Name + " 的設定已全部重設。"));
		}

		private static void CaptureKey()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			Event current = Event.current;
			if (current == null || (int)current.type != 4 || (int)current.keyCode == 0)
			{
				return;
			}
			ConfigEntryBase target = _capturing;
			KeyCode key = current.keyCode;
			current.Use();
			Defer(delegate
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Invalid comparison between Unknown and I4
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				_capturing = null;
				if ((int)key != 27)
				{
					Set(target, (object)new KeyboardShortcut(key, Array.Empty<KeyCode>()));
				}
			});
		}

		private static bool IsNumeric(Type t)
		{
			if (!(t == typeof(int)) && !(t == typeof(float)) && !(t == typeof(double)) && !(t == typeof(long)) && !(t == typeof(short)))
			{
				return t == typeof(byte);
			}
			return true;
		}

		private static bool TryRange(ConfigEntryBase e, out float min, out float max)
		{
			min = 0f;
			max = 1f;
			if (e.Description == null || e.Description.AcceptableValues == null)
			{
				return false;
			}
			object acceptableValues = e.Description.AcceptableValues;
			PropertyInfo property = acceptableValues.GetType().GetProperty("MinValue");
			PropertyInfo property2 = acceptableValues.GetType().GetProperty("MaxValue");
			if (property == null || property2 == null)
			{
				return false;
			}
			try
			{
				min = Convert.ToSingle(property.GetValue(acceptableValues, null), CultureInfo.InvariantCulture);
				max = Convert.ToSingle(property2.GetValue(acceptableValues, null), CultureInfo.InvariantCulture);
			}
			catch (Exception)
			{
				return false;
			}
			return max > min;
		}

		private static string Format(float v, Type t)
		{
			if (t == typeof(int) || t == typeof(long) || t == typeof(short) || t == typeof(byte))
			{
				return Mathf.RoundToInt(v).ToString(CultureInfo.InvariantCulture);
			}
			return v.ToString("0.###", CultureInfo.InvariantCulture);
		}
	}
	internal static class Theme
	{
		internal static readonly Color Bg = Hex("1B1D21");

		internal static readonly Color Card = Hex("24272C");

		internal static readonly Color CardHi = Hex("2E333A");

		internal static readonly Color Field = Hex("141619");

		internal static readonly Color Border = Hex("3A3F46");

		internal static readonly Color Line = Hex("2C3036");

		internal static readonly Color Text = Hex("E6E8EB");

		internal static readonly Color Dim = Hex("8B939C");

		internal static readonly Color Accent = Hex("4FB3D9");

		internal static readonly Color AccentHi = Hex("7ACFF0");

		internal static readonly Color AccentBg = Hex("1F3742");

		internal static readonly Color Safe = Hex("6FCF97");

		internal static readonly Color Caution = Hex("F2C94C");

		internal static readonly Color Danger = Hex("EB5757");

		internal static GUISkin Skin;

		internal static GUIStyle CardBox;

		internal static GUIStyle Inset;

		internal static GUIStyle Stripe;

		internal static GUIStyle Sep;

		internal static GUIStyle Title;

		internal static GUIStyle Head;

		internal static GUIStyle Label;

		internal static GUIStyle DimLabel;

		internal static GUIStyle WarnLabel;

		internal static GUIStyle Badge;

		internal static GUIStyle Pill;

		internal static GUIStyle Tab;

		internal static GUIStyle Run;

		internal static GUIStyle ListItem;

		internal static GUIStyle ArgLabel;

		internal static GUIStyle Mono;

		private static bool _built;

		private static readonly List<Texture2D> Textures = new List<Texture2D>();

		internal static void Build(Font font)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			//IL_00c7: 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_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Expected O, but got Unknown
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Expected O, but got Unknown
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Expected O, but got Unknown
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			//IL_034c: 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_0379: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_042a: Unknown result type (might be due to invalid IL or missing references)
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0435: Unknown result type (might be due to invalid IL or missing references)
			//IL_043f: Expected O, but got Unknown
			//IL_043f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0444: Unknown result type (might be due to invalid IL or missing references)
			//IL_044e: Expected O, but got Unknown
			//IL_0453: Expected O, but got Unknown
			//IL_045d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0462: Unknown result type (might be due to invalid IL or missing references)
			//IL_0468: Unknown result type (might be due to invalid IL or missing references)
			//IL_046d: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0487: Unknown result type (might be due to invalid IL or missing references)
			//IL_048c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0496: Expected O, but got Unknown
			//IL_049b: Expected O, but got Unknown
			//IL_049b: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ba: Expected O, but got Unknown
			//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e3: Expected O, but got Unknown
			//IL_04e8: Expected O, but got Unknown
			//IL_04f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0506: Unknown result type (might be due to invalid IL or missing references)
			//IL_050c: Unknown result type (might be due to invalid IL or missing references)
			//IL_051b: Expected O, but got Unknown
			//IL_0525: Unknown result type (might be due to invalid IL or missing references)
			//IL_052a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0531: Unknown result type (might be due to invalid IL or missing references)
			//IL_053e: Expected O, but got Unknown
			//IL_0548: Unknown result type (might be due to invalid IL or missing references)
			//IL_0552: Expected O, but got Unknown
			//IL_055c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0561: Unknown result type (might be due to invalid IL or missing references)
			//IL_0568: Unknown result type (might be due to invalid IL or missing references)
			//IL_056e: Unknown result type (might be due to invalid IL or missing references)
			//IL_057d: Expected O, but got Unknown
			//IL_0587: Unknown result type (might be due to invalid IL or missing references)
			//IL_058c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0593: Unknown result type (might be due to invalid IL or missing references)
			//IL_059b: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b0: Expected O, but got Unknown
			//IL_05ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e5: Expected O, but got Unknown
			//IL_05ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0602: Unknown result type (might be due to invalid IL or missing references)
			//IL_060c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0618: Expected O, but got Unknown
			//IL_0622: Unknown result type (might be due to invalid IL or missing references)
			//IL_0627: Unknown result type (might be due to invalid IL or missing references)
			//IL_062f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0636: Unknown result type (might be due to invalid IL or missing references)
			//IL_0641: Unknown result type (might be due to invalid IL or missing references)
			//IL_0650: Expected O, but got Unknown
			//IL_065a: Unknown result type (might be due to invalid IL or missing references)
			//IL_065f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0667: Unknown result type (might be due to invalid IL or missing references)
			//IL_066c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0676: Expected O, but got Unknown
			//IL_067b: Expected O, but got Unknown
			//IL_0685: Unknown result type (might be due to invalid IL or missing references)
			//IL_068a: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_070c: Unknown result type (might be due to invalid IL or missing references)
			//IL_071b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0720: Unknown result type (might be due to invalid IL or missing references)
			//IL_0727: Unknown result type (might be due to invalid IL or missing references)
			//IL_072d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0737: Expected O, but got Unknown
			//IL_0737: Unknown result type (might be due to invalid IL or missing references)
			//IL_073f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0744: Unknown result type (might be due to invalid IL or missing references)
			//IL_074e: Expected O, but got Unknown
			//IL_0753: Expected O, but got Unknown
			//IL_075d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0762: Unknown result type (might be due to invalid IL or missing references)
			//IL_0769: Unknown result type (might be due to invalid IL or missing references)
			//IL_0776: Expected O, but got Unknown
			//IL_0780: Unknown result type (might be due to invalid IL or missing references)
			//IL_0785: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_07df: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_080c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0820: Unknown result type (might be due to invalid IL or missing references)
			//IL_0825: Unknown result type (might be due to invalid IL or missing references)
			//IL_082c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0831: Unknown result type (might be due to invalid IL or missing references)
			//IL_083b: Expected O, but got Unknown
			//IL_083b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0848: Expected O, but got Unknown
			//IL_0852: Unknown result type (might be due to invalid IL or missing references)
			//IL_086b: Unknown result type (might be due to invalid IL or missing references)
			//IL_087f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0898: Unknown result type (might be due to invalid IL or missing references)
			if (!_built)
			{
				_built = true;
				Skin = Object.Instantiate<GUISkin>(GUI.skin);
				((Object)Skin).hideFlags = (HideFlags)61;
				if ((Object)(object)font != (Object)null)
				{
					Skin.font = font;
				}
				Skin.window.normal.background = Framed(Bg, Border);
				Skin.window.onNormal.background = Skin.window.normal.background;
				Skin.window.border = One();
				Skin.window.padding = new RectOffset(12, 12, 30, 10);
				Skin.window.normal.textColor = Accent;
				Skin.window.onNormal.textColor = Accent;
				Skin.window.fontStyle = (FontStyle)1;
				Skin.window.fontSize = 14;
				Skin.window.alignment = (TextAnchor)1;
				Skin.window.contentOffset = new Vector2(0f, 8f);
				Skin.box.normal.background = Framed(Card, Line);
				Skin.box.border = One();
				Skin.box.padding = new RectOffset(8, 8, 8, 8);
				Skin.box.normal.textColor = Text;
				Tint(Skin.button, CardHi, Border, Text, Hex("383E46"), AccentBg, Accent);
				Skin.button.padding = new RectOffset(10, 10, 4, 4);
				Skin.button.fontSize = 13;
				Skin.button.alignment = (TextAnchor)4;
				Skin.textField.normal.background = Framed(Field, Border);
				Skin.textField.focused.background = Framed(Field, Accent);
				Skin.textField.hover.background = Framed(Field, Hex("4A5058"));
				Skin.textField.border = One();
				Skin.textField.padding = new RectOffset(6, 6, 4, 4);
				Skin.textField.normal.textColor = Text;
				Skin.textField.focused.textColor = Text;
				Skin.textField.hover.textColor = Text;
				Skin.textField.fontSize = 13;
				Skin.label.normal.textColor = Text;
				Skin.label.fontSize = 13;
				Skin.verticalScrollbar.normal.background = Solid(Field);
				Skin.verticalScrollbarThumb.normal.background = Framed(Hex("454B54"), Hex("545C66"));
				Skin.verticalScrollbarThumb.border = One();
				Skin.verticalScrollbarUpButton.normal.background = null;
				Skin.verticalScrollbarDownButton.normal.background = null;
				Skin.horizontalScrollbar.normal.background = Solid(Field);
				Skin.horizontalScrollbarThumb.normal.background = Skin.verticalScrollbarThumb.normal.background;
				Skin.horizontalScrollbarThumb.border = One();
				CardBox = new GUIStyle(Skin.box)
				{
					padding = new RectOffset(0, 10, 8, 8),
					margin = new RectOffset(0, 0, 0, 6)
				};
				GUIStyle val = new GUIStyle(Skin.box);
				val.normal.background = Framed(Field, Line);
				val.border = One();
				val.padding = new RectOffset(8, 8, 6, 6);
				Inset = val;
				GUIStyle val2 = new GUIStyle();
				val2.normal.background = Solid(Color.white);
				Stripe = val2;
				GUIStyle val3 = new GUIStyle();
				val3.normal.background = Solid(Line);
				val3.margin = new RectOffset(0, 0, 6, 6);
				Sep = val3;
				GUIStyle val4 = new GUIStyle(Skin.label)
				{
					fontStyle = (FontStyle)1,
					fontSize = 16
				};
				val4.normal.textColor = Accent;
				Title = val4;
				Head = new GUIStyle(Skin.label)
				{
					fontStyle = (FontStyle)1,
					fontSize = 13
				};
				Label = new GUIStyle(Skin.label);
				GUIStyle val5 = new GUIStyle(Skin.label)
				{
					wordWrap = true
				};
				val5.normal.textColor = Dim;
				DimLabel = val5;
				GUIStyle val6 = new GUIStyle(Skin.label)
				{
					wordWrap = true,
					fontSize = 12
				};
				val6.normal.textColor = Caution;
				WarnLabel = val6;
				Badge = new GUIStyle(Skin.label)
				{
					fontStyle = (FontStyle)1,
					fontSize = 11,
					alignment = (TextAnchor)4,
					fixedWidth = 40f
				};
				GUIStyle val7 = new GUIStyle(Skin.label)
				{
					fontSize = 12
				};
				val7.normal.textColor = Dim;
				val7.alignment = (TextAnchor)5;
				ArgLabel = val7;
				GUIStyle val8 = new GUIStyle(Skin.label)
				{
					fontSize = 12,
					wordWrap = true
				};
				val8.normal.textColor = Hex("B9C0C8");
				Mono = val8;
				Pill = new GUIStyle(Skin.button)
				{
					fontSize = 12,
					padding = new RectOffset(8, 8, 3, 3)
				};
				Pill.onNormal.background = Framed(AccentBg, Accent);
				Pill.onHover.background = Framed(Hex("27424F"), AccentHi);
				Pill.onActive.background = Pill.onNormal.background;
				Pill.onNormal.textColor = AccentHi;
				Pill.onHover.textColor = AccentHi;
				Pill.onActive.textColor = AccentHi;
				Tab = new GUIStyle(Pill)
				{
					alignment = (TextAnchor)3,
					padding = new RectOffset(12, 8, 5, 5),
					fontSize = 13,
					margin = new RectOffset(0, 0, 0, 3)
				};
				Run = new GUIStyle(Skin.button)
				{
					fontStyle = (FontStyle)1,
					fontSize = 13
				};
				Run.normal.background = Framed(AccentBg, Accent);
				Run.hover.background = Framed(Hex("2A4A59"), AccentHi);
				Run.active.background = Framed(Accent, AccentHi);
				Run.normal.textColor = AccentHi;
				Run.hover.textColor = Color.white;
				Run.active.textColor = Hex("0F1417");
				ListItem = new GUIStyle(Skin.label)
				{
					alignment = (TextAnchor)3,
					padding = new RectOffset(8, 8, 5, 5),
					fontSize = 13
				};
				ListItem.hover.background = Solid(CardHi);
				ListItem.hover.textColor = AccentHi;
				ListItem.active.background = Solid(AccentBg);
				ListItem.active.textColor = AccentHi;
			}
		}

		internal static void Separator()
		{
			GUILayout.Box(GUIContent.none, Sep, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Height(1f),
				GUILayout.ExpandWidth(true)
			});
		}

		internal static void VStripe(Color color, float width = 3f)
		{
			//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_0006: 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)
			Color color2 = GUI.color;
			GUI.color = color;
			GUILayout.Box(GUIContent.none, Stripe, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(width),
				GUILayout.ExpandHeight(true)
			});
			GUI.color = color2;
		}

		private static RectOffset One()
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			return new RectOffset(1, 1, 1, 1);
		}

		private static void Tint(GUIStyle s, Color fill, Color border, Color text, Color? hoverFill = null, Color? activeFill = null, Color? activeBorder = null)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_0034: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			s.normal.background = Framed(fill, border);
			s.hover.background = Framed(hoverFill ?? fill, border);
			s.active.background = Framed(activeFill ?? fill, activeBorder ?? border);
			s.focused.background = s.normal.background;
			s.border = One();
			s.normal.textColor = text;
			s.hover.textColor = text;
			s.active.textColor = text;
			s.focused.textColor = text;
		}

		private static Texture2D Solid(Color c)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_0017: 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)
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			Color[] array = (Color[])(object)new Color[4];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = c;
			}
			val.SetPixels(array);
			Finish(val);
			return val;
		}

		private static Texture2D Framed(Color fill, Color border)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			//IL_0031: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(4, 4, (TextureFormat)4, false);
			Color[] array = (Color[])(object)new Color[16];
			for (int i = 0; i < 4; i++)
			{
				for (int j = 0; j < 4; j++)
				{
					array[i * 4 + j] = ((j == 0 || i == 0 || j == 3 || i == 3) ? border : fill);
				}
			}
			val.SetPixels(array);
			Finish(val);
			return val;
		}

		private static void Finish(Texture2D t)
		{
			((Texture)t).filterMode = (FilterMode)0;
			((Texture)t).wrapMode = (TextureWrapMode)1;
			((Object)t).hideFlags = (HideFlags)61;
			t.Apply();
			Textures.Add(t);
		}

		private static Color Hex(string hex)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			int num = Convert.ToInt32(hex.Substring(0, 2), 16);
			int num2 = Convert.ToInt32(hex.Substring(2, 2), 16);
			int num3 = Convert.ToInt32(hex.Substring(4, 2), 16);
			return new Color((float)num / 255f, (float)num2 / 255f, (float)num3 / 255f, 1f);
		}
	}
	internal static class ModInfo
	{
		public const string Name = "HtF Config Menu";

		public const string Version = "1.0.0";
	}
}