Decompiled source of ModConfigs v1.0.6

ModConfigs.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GUIFramework;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Valheim.SettingsGui;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: AssemblyCompany("ModConfigs")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.6.0")]
[assembly: AssemblyInformationalVersion("1.0.6")]
[assembly: AssemblyProduct("ModConfigs")]
[assembly: AssemblyTitle("ModConfigs")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.6.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ModdedWolfsConfigs
{
	public static class ModdedWolfsConfigsAPI
	{
		public static void OpenConfigPanel()
		{
			ConfigPanelOpener.Open();
		}
	}
	public sealed class ConfigurationManagerAttributes
	{
		public bool? Browsable;

		public bool? IsAdminOnly;

		public bool? IsAdvanced;

		public int? Order;

		public string DispName;

		public string Description;

		public string Category;

		public bool? ReadOnly;

		public bool? HideDefaultButton;

		public object DefaultValue;

		public bool? ShowRangeAsPercent;

		public bool? HideSettingName;
	}
	internal static class ClientLocalBindings
	{
		internal static bool IsBinding(ConfigEntryBase entry)
		{
			if (entry == null)
			{
				return false;
			}
			Type settingType = entry.SettingType;
			if (settingType == null)
			{
				return false;
			}
			if (settingType == typeof(KeyCode) || settingType == typeof(KeyboardShortcut))
			{
				return true;
			}
			return (settingType.FullName ?? string.Empty).IndexOf("KeyboardShortcut", StringComparison.OrdinalIgnoreCase) >= 0;
		}
	}
	internal static class ConfigApply
	{
		internal static void PersistAfterLocalChange(ConfigEntryBase entry)
		{
			if (entry == null)
			{
				return;
			}
			try
			{
				ConfigFile configFile = entry.ConfigFile;
				if (configFile != null)
				{
					configFile.Save();
				}
			}
			catch (Exception ex)
			{
				ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to save config: " + ex.Message));
			}
		}
	}
	internal sealed class DiscoveredPlugin
	{
		public string Guid;

		public string Name;

		public string Version;

		public BaseUnityPlugin Plugin;

		public List<DiscoveredSection> Sections = new List<DiscoveredSection>();
	}
	internal sealed class DiscoveredSection
	{
		public string Name;

		public List<ConfigEntryBase> Entries = new List<ConfigEntryBase>();
	}
	internal static class ConfigDiscovery
	{
		private static readonly HashSet<string> HiddenConfigKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "LastSelectedModGuid", "ShowMenuButton" };

		private static bool _loggedHiddenKeyFilter;

		internal static bool IsHiddenConfigKey(string key)
		{
			if (!string.IsNullOrEmpty(key))
			{
				return HiddenConfigKeys.Contains(key);
			}
			return false;
		}

		internal static bool ShouldRenderEntry(ConfigEntryBase entry)
		{
			if (((entry != null) ? entry.Definition : null) == (ConfigDefinition)null)
			{
				return false;
			}
			return !IsHiddenConfigKey(entry.Definition.Key);
		}

		internal static List<DiscoveredPlugin> Discover()
		{
			List<DiscoveredPlugin> list = new List<DiscoveredPlugin>();
			IEnumerable<KeyValuePair<string, PluginInfo>> enumerable;
			try
			{
				enumerable = Chainloader.PluginInfos.Where(delegate(KeyValuePair<string, PluginInfo> p)
				{
					PluginInfo value3 = p.Value;
					return ((value3 != null) ? value3.Metadata : null) != null;
				}).OrderBy<KeyValuePair<string, PluginInfo>, string>((KeyValuePair<string, PluginInfo> p) => p.Value.Metadata.Name ?? p.Value.Metadata.GUID ?? p.Key ?? string.Empty, StringComparer.OrdinalIgnoreCase);
			}
			catch (Exception ex)
			{
				ModdedWolfsConfigsPlugin.Log.LogWarning((object)("ConfigDiscovery: failed to enumerate plugins: " + ex.Message));
				return list;
			}
			foreach (KeyValuePair<string, PluginInfo> item in enumerable)
			{
				PluginInfo value = item.Value;
				string text = item.Key ?? "(unknown)";
				try
				{
					if (((value != null) ? value.Metadata : null) == null)
					{
						continue;
					}
					text = ((!string.IsNullOrEmpty(value.Metadata.Name)) ? (value.Metadata.Name + " (" + value.Metadata.GUID + ")") : (value.Metadata.GUID ?? item.Key ?? "(unknown)"));
					BaseUnityPlugin instance = value.Instance;
					if ((Object)(object)instance == (Object)null || (ModdedWolfsConfigsPlugin.HideSelfFromList.Value && value.Metadata.GUID == "ModdedWolf.ModConfigs"))
					{
						continue;
					}
					ConfigFile config = instance.Config;
					if (config == null)
					{
						continue;
					}
					Dictionary<string, DiscoveredSection> dictionary = new Dictionary<string, DiscoveredSection>(StringComparer.OrdinalIgnoreCase);
					foreach (ConfigDefinition key in config.Keys)
					{
						if (key == (ConfigDefinition)null)
						{
							continue;
						}
						if (IsHiddenConfigKey(key.Key))
						{
							if (!_loggedHiddenKeyFilter && value.Metadata.GUID == "ModdedWolf.ModConfigs")
							{
								_loggedHiddenKeyFilter = true;
								ModdedWolfsConfigsPlugin.Log.LogInfo((object)("ConfigDiscovery: hiding internal key '" + key.Key + "' from UI (still stored in cfg)."));
							}
							continue;
						}
						ConfigEntryBase val = config[key];
						if (!(((val != null) ? val.Definition : null) == (ConfigDefinition)null) && IsBrowsable(val))
						{
							string text2 = key.Section ?? string.Empty;
							if (!dictionary.TryGetValue(text2, out var value2))
							{
								value2 = (dictionary[text2] = new DiscoveredSection
								{
									Name = text2
								});
							}
							value2.Entries.Add(val);
						}
					}
					if (dictionary.Count == 0)
					{
						continue;
					}
					DiscoveredPlugin discoveredPlugin = new DiscoveredPlugin
					{
						Guid = (value.Metadata.GUID ?? item.Key ?? string.Empty),
						Name = (value.Metadata.Name ?? value.Metadata.GUID ?? item.Key ?? "Unknown"),
						Version = (value.Metadata.Version?.ToString() ?? ""),
						Plugin = instance
					};
					foreach (DiscoveredSection item2 in dictionary.Values.OrderByDescending(SectionHasBinding).ThenByDescending((DiscoveredSection s) => string.Equals(s.Name, "General", StringComparison.OrdinalIgnoreCase)).ThenBy<DiscoveredSection, string>((DiscoveredSection s) => s.Name ?? string.Empty, StringComparer.OrdinalIgnoreCase))
					{
						item2.Entries = item2.Entries.OrderByDescending(ClientLocalBindings.IsBinding).ThenByDescending(GetOrder).ThenBy<ConfigEntryBase, string>(delegate(ConfigEntryBase e)
						{
							ConfigDefinition definition = e.Definition;
							return ((definition != null) ? definition.Key : null) ?? string.Empty;
						}, StringComparer.OrdinalIgnoreCase)
							.ToList();
						discoveredPlugin.Sections.Add(item2);
					}
					list.Add(discoveredPlugin);
				}
				catch (Exception ex2)
				{
					ModdedWolfsConfigsPlugin.Log.LogWarning((object)("ConfigDiscovery: skipped plugin '" + text + "': " + ex2.Message));
				}
			}
			return list;
		}

		private static bool IsBrowsable(ConfigEntryBase entry)
		{
			if (((entry != null) ? entry.Definition : null) == (ConfigDefinition)null)
			{
				return false;
			}
			if (IsHiddenConfigKey(entry.Definition.Key))
			{
				return false;
			}
			ConfigDescription description = entry.Description;
			object[] array = ((description != null) ? description.Tags : null);
			if (array == null)
			{
				return true;
			}
			foreach (object obj in array)
			{
				if (obj == null)
				{
					continue;
				}
				if (obj is ConfigurationManagerAttributes { Browsable: var browsable } configurationManagerAttributes)
				{
					if (browsable == false)
					{
						return false;
					}
					if (configurationManagerAttributes.IsAdvanced == true && !ModdedWolfsConfigsPlugin.ShowAdvancedSettings.Value)
					{
						return false;
					}
					continue;
				}
				PropertyInfo property = obj.GetType().GetProperty("Browsable", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.PropertyType == typeof(bool?) && (bool?)property.GetValue(obj, null) == false)
				{
					return false;
				}
				PropertyInfo property2 = obj.GetType().GetProperty("IsAdvanced", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property2 != null && property2.PropertyType == typeof(bool?) && (bool?)property2.GetValue(obj, null) == true && !ModdedWolfsConfigsPlugin.ShowAdvancedSettings.Value)
				{
					return false;
				}
			}
			return true;
		}

		private static bool SectionHasBinding(DiscoveredSection section)
		{
			if (section?.Entries == null)
			{
				return false;
			}
			for (int i = 0; i < section.Entries.Count; i++)
			{
				if (ClientLocalBindings.IsBinding(section.Entries[i]))
				{
					return true;
				}
			}
			return false;
		}

		private static int GetOrder(ConfigEntryBase entry)
		{
			object obj;
			if (entry == null)
			{
				obj = null;
			}
			else
			{
				ConfigDescription description = entry.Description;
				obj = ((description != null) ? description.Tags : null);
			}
			object[] array = (object[])obj;
			if (array == null)
			{
				return 0;
			}
			foreach (object obj2 in array)
			{
				if (obj2 is ConfigurationManagerAttributes configurationManagerAttributes && configurationManagerAttributes.Order.HasValue)
				{
					return configurationManagerAttributes.Order.Value;
				}
				PropertyInfo propertyInfo = obj2?.GetType().GetProperty("Order", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (propertyInfo != null && propertyInfo.PropertyType == typeof(int?))
				{
					int? num = (int?)propertyInfo.GetValue(obj2, null);
					if (num.HasValue)
					{
						return num.Value;
					}
				}
			}
			return 0;
		}

		internal static string GetDisplayName(ConfigEntryBase entry)
		{
			object obj;
			if (entry == null)
			{
				obj = null;
			}
			else
			{
				ConfigDescription description = entry.Description;
				obj = ((description != null) ? description.Tags : null);
			}
			object[] array = (object[])obj;
			if (array != null)
			{
				for (int i = 0; i < array.Length; i++)
				{
					if (array[i] is ConfigurationManagerAttributes configurationManagerAttributes && !string.IsNullOrEmpty(configurationManagerAttributes.DispName))
					{
						return configurationManagerAttributes.DispName;
					}
					PropertyInfo propertyInfo = array[i]?.GetType().GetProperty("DispName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (propertyInfo != null && propertyInfo.PropertyType == typeof(string))
					{
						string text = propertyInfo.GetValue(array[i], null) as string;
						if (!string.IsNullOrEmpty(text))
						{
							return text;
						}
					}
				}
			}
			object obj2;
			if (entry == null)
			{
				obj2 = null;
			}
			else
			{
				ConfigDefinition definition = entry.Definition;
				obj2 = ((definition != null) ? definition.Key : null);
			}
			if (obj2 == null)
			{
				obj2 = string.Empty;
			}
			return (string)obj2;
		}
	}
	internal static class PauseMenuButton
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__Open;
		}

		internal static void Refresh()
		{
			try
			{
				bool flag = ModdedWolfsConfigsPlugin.ShowMainMenuButton == null || ModdedWolfsConfigsPlugin.ShowMainMenuButton.Value;
				bool flag2 = ModdedWolfsConfigsPlugin.ShowPauseMenuButton == null || ModdedWolfsConfigsPlugin.ShowPauseMenuButton.Value;
				if ((Object)(object)FejdStartup.instance != (Object)null)
				{
					Transform val = (((Object)(object)FejdStartup.instance.m_menuList != (Object)null) ? FejdStartup.instance.m_menuList.transform : null);
					SetupFromHierarchy(FindMenuEntries(val), flag);
					if ((Object)(object)val != (Object)null)
					{
						FejdStartup.instance.m_menuButtons = ((Component)val).GetComponentsInChildren<Button>(false);
					}
					if (!flag)
					{
						HideNamedUnder(((Component)FejdStartup.instance).transform);
					}
				}
				if ((Object)(object)Menu.instance != (Object)null)
				{
					SetupPauseMenu(flag2);
					if (!flag2)
					{
						HideNamedUnder(((Component)Menu.instance).transform);
					}
				}
			}
			catch (Exception ex)
			{
				ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to refresh menu button: " + ex.Message));
			}
		}

		internal static bool IsModConfigsControlActive()
		{
			//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_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_004d: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)EventSystem.current == (Object)null)
			{
				return false;
			}
			if (IsNamedModButton(EventSystem.current.currentSelectedGameObject))
			{
				return true;
			}
			if (Input.GetMouseButton(0) || Input.GetMouseButtonUp(0))
			{
				PointerEventData val = new PointerEventData(EventSystem.current)
				{
					position = Vector2.op_Implicit(Input.mousePosition)
				};
				List<RaycastResult> list = new List<RaycastResult>();
				EventSystem.current.RaycastAll(val, list);
				for (int i = 0; i < list.Count; i++)
				{
					RaycastResult val2 = list[i];
					if (IsNamedModButton(((RaycastResult)(ref val2)).gameObject))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool IsNamedModButton(GameObject go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return false;
			}
			Transform val = go.transform;
			while ((Object)(object)val != (Object)null)
			{
				if (((Object)val).name == "ModdedWolfsConfigs")
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		private static void SetupPauseMenu(bool show)
		{
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			Menu instance = Menu.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			Button val = instance.m_settingsButton;
			Transform val2 = null;
			if ((Object)(object)val != (Object)null)
			{
				val2 = ((Component)val).transform.parent;
			}
			if ((Object)(object)val2 == (Object)null && (Object)(object)instance.menuEntriesParent != (Object)null)
			{
				val2 = (Transform)(object)instance.menuEntriesParent;
			}
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = FindMenuEntries(instance.m_menuDialog);
			}
			if ((Object)(object)val == (Object)null && (Object)(object)val2 != (Object)null)
			{
				val = FindSettingsButtonUnder(val2);
			}
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null))
			{
				Button val3 = EnsureModButton(val2, val);
				ApplyLabel(((Component)val3).gameObject);
				RewireClick(val3);
				((Component)val3).gameObject.SetActive(show);
				object obj;
				if (!((Object)(object)instance.m_logoutButton != (Object)null))
				{
					Navigation navigation = ((Selectable)val).navigation;
					Selectable selectOnDown = ((Navigation)(ref navigation)).selectOnDown;
					obj = ((selectOnDown is Button) ? selectOnDown : null);
				}
				else
				{
					obj = instance.m_logoutButton;
				}
				Button nextButton = (Button)obj;
				WireNavigation(val, val3, nextButton, show);
			}
		}

		private static void SetupFromHierarchy(Transform menuEntries, bool show)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)menuEntries == (Object)null)
			{
				return;
			}
			Button val = FindSettingsButtonUnder(menuEntries);
			if (!((Object)(object)val == (Object)null))
			{
				Button val2 = EnsureModButton(menuEntries, val);
				ApplyLabel(((Component)val2).gameObject);
				RewireClick(val2);
				((Component)val2).gameObject.SetActive(show);
				Navigation navigation = ((Selectable)val).navigation;
				Selectable selectOnDown = ((Navigation)(ref navigation)).selectOnDown;
				Button val3 = (Button)(object)((selectOnDown is Button) ? selectOnDown : null);
				if ((Object)(object)val3 != (Object)null && ((Object)val3).name == "ModdedWolfsConfigs")
				{
					navigation = ((Selectable)val3).navigation;
					Selectable selectOnDown2 = ((Navigation)(ref navigation)).selectOnDown;
					val3 = (Button)(object)((selectOnDown2 is Button) ? selectOnDown2 : null);
				}
				WireNavigation(val, val2, val3, show);
			}
		}

		private static Button EnsureModButton(Transform parent, Button settingsButton)
		{
			Transform val = parent.Find("ModdedWolfsConfigs");
			GameObject val2 = (((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null);
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = Object.Instantiate<GameObject>(((Component)settingsButton).gameObject, parent);
				((Object)val2).name = "ModdedWolfsConfigs";
				val2.transform.SetSiblingIndex(((Component)settingsButton).transform.GetSiblingIndex() + 1);
			}
			Button component = val2.GetComponent<Button>();
			if ((Object)(object)component == (Object)null)
			{
				throw new InvalidOperationException("Cloned Mod Configs control is missing a Button.");
			}
			return component;
		}

		private static void RewireClick(Button button)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			if ((Object)(object)button == (Object)null)
			{
				return;
			}
			button.onClick = new ButtonClickedEvent();
			ButtonClickedEvent onClick = button.onClick;
			object obj = <>O.<0>__Open;
			if (obj == null)
			{
				UnityAction val = ConfigPanelOpener.Open;
				<>O.<0>__Open = val;
				obj = (object)val;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			EventTrigger[] componentsInChildren = ((Component)button).GetComponentsInChildren<EventTrigger>(true);
			foreach (EventTrigger val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null) && val2.triggers != null)
				{
					val2.triggers.RemoveAll((Entry entry) => entry != null && ((int)entry.eventID == 4 || (int)entry.eventID == 15));
				}
			}
		}

		private static void ApplyLabel(GameObject menuButton)
		{
			TMP_Text componentInChildren = menuButton.GetComponentInChildren<TMP_Text>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.text = "Mod Configs";
			}
			Text componentInChildren2 = menuButton.GetComponentInChildren<Text>(true);
			if ((Object)(object)componentInChildren2 != (Object)null)
			{
				componentInChildren2.text = "Mod Configs";
			}
		}

		private static Button FindSettingsButtonUnder(Transform menuEntries)
		{
			Transform val = menuEntries.Find("Settings");
			if ((Object)(object)val == (Object)null)
			{
				for (int i = 0; i < menuEntries.childCount; i++)
				{
					Transform child = menuEntries.GetChild(i);
					if ((Object)(object)child != (Object)null && ((Object)child).name.IndexOf("Settings", StringComparison.OrdinalIgnoreCase) >= 0 && ((Object)child).name != "ModdedWolfsConfigs")
					{
						val = child;
						break;
					}
				}
			}
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((Component)val).GetComponent<Button>();
		}

		private static Transform FindMenuEntries(Transform root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			Transform val = root.Find("MenuEntries");
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null && ((Object)componentsInChildren[i]).name == "MenuEntries")
				{
					return componentsInChildren[i];
				}
			}
			return null;
		}

		private static void HideNamedUnder(Transform root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null && ((Object)componentsInChildren[i]).name == "ModdedWolfsConfigs")
				{
					((Component)componentsInChildren[i]).gameObject.SetActive(false);
				}
			}
		}

		private static void WireNavigation(Button settingsButton, Button modButton, Button nextButton, bool show)
		{
			//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_004b: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_0085: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)settingsButton == (Object)null || (Object)(object)modButton == (Object)null)
			{
				return;
			}
			if ((Object)(object)nextButton != (Object)null && ((Object)nextButton).name == "ModdedWolfsConfigs")
			{
				Navigation navigation = ((Selectable)nextButton).navigation;
				Selectable selectOnDown = ((Navigation)(ref navigation)).selectOnDown;
				nextButton = (Button)(object)((selectOnDown is Button) ? selectOnDown : null);
			}
			Navigation navigation2 = ((Selectable)settingsButton).navigation;
			Navigation navigation3 = ((Selectable)modButton).navigation;
			if (show)
			{
				((Navigation)(ref navigation2)).selectOnDown = (Selectable)(object)modButton;
				((Navigation)(ref navigation3)).selectOnUp = (Selectable)(object)settingsButton;
				((Navigation)(ref navigation3)).selectOnDown = (Selectable)(object)nextButton;
				((Navigation)(ref navigation3)).mode = (Mode)4;
				((Selectable)modButton).navigation = navigation3;
				if ((Object)(object)nextButton != (Object)null)
				{
					Navigation navigation4 = ((Selectable)nextButton).navigation;
					((Navigation)(ref navigation4)).selectOnUp = (Selectable)(object)modButton;
					((Selectable)nextButton).navigation = navigation4;
				}
			}
			else if ((Object)(object)nextButton != (Object)null)
			{
				((Navigation)(ref navigation2)).selectOnDown = (Selectable)(object)nextButton;
				Navigation navigation5 = ((Selectable)nextButton).navigation;
				((Navigation)(ref navigation5)).selectOnUp = (Selectable)(object)settingsButton;
				((Selectable)nextButton).navigation = navigation5;
			}
			((Selectable)settingsButton).navigation = navigation2;
		}
	}
	[BepInPlugin("ModdedWolf.ModConfigs", "Mod Configs", "1.0.6")]
	public class ModdedWolfsConfigsPlugin : BaseUnityPlugin
	{
		public const string GUID = "ModdedWolf.ModConfigs";

		private const string LegacyGuid = "ModdedWolf.ModdedWolfsConfigs";

		public const string NAME = "Mod Configs";

		public const string VERSION = "1.0.6";

		internal const string MenuButtonName = "ModdedWolfsConfigs";

		internal const string MenuButtonCaption = "Mod Configs";

		internal const string PanelTitle = "Mod Configs";

		internal static ConfigEntry<bool> ShowMainMenuButton;

		internal static ConfigEntry<bool> ShowPauseMenuButton;

		internal static ConfigEntry<bool> ShowAdvancedSettings;

		internal static ConfigEntry<bool> HideSelfFromList;

		internal static ConfigEntry<bool> RememberLastMod;

		internal const string LastSelectedModGuidKey = "LastSelectedModGuid";

		internal static ConfigEntry<string> LastSelectedModGuid;

		private Harmony _harmony;

		internal static ModdedWolfsConfigsPlugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Expected O, but got Unknown
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			TryMigrateLegacyConfigFile();
			ShowMainMenuButton = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowMainMenuButton", false, "Show Mod Configs on the main menu (title screen).");
			ShowPauseMenuButton = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowPauseMenuButton", true, "Show Mod Configs on the in-game pause menu.");
			TryMigrateLegacyShowMenuButton();
			ShowAdvancedSettings = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowAdvancedSettings", false, "Show settings marked as advanced (ConfigurationManagerAttributes.IsAdvanced).");
			HideSelfFromList = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "HideSelfFromList", false, "Hide this mod's own settings from the in-game config panel.");
			RememberLastMod = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RememberLastMod", true, "When enabled, reopen Mod Configs on the last mod you had selected.");
			LastSelectedModGuid = ((BaseUnityPlugin)this).Config.Bind<string>("General", "LastSelectedModGuid", "", new ConfigDescription("GUID of the last mod opened in Mod Configs (remembered between sessions).", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = false
				}
			}));
			ShowMainMenuButton.SettingChanged += delegate
			{
				PauseMenuButton.Refresh();
			};
			ShowPauseMenuButton.SettingChanged += delegate
			{
				PauseMenuButton.Refresh();
			};
			_harmony = new Harmony("ModdedWolf.ModConfigs");
			_harmony.PatchAll();
			Log.LogInfo((object)"Mod Configs v1.0.6 loaded (client configs).");
		}

		private void TryMigrateLegacyConfigFile()
		{
			try
			{
				string configPath = Paths.ConfigPath;
				string text = Path.Combine(configPath, "ModdedWolf.ModConfigs.cfg");
				string text2 = Path.Combine(configPath, "ModdedWolf.ModdedWolfsConfigs.cfg");
				if (File.Exists(text2) && !File.Exists(text))
				{
					File.Copy(text2, text);
					Log.LogInfo((object)"Migrated config from ModdedWolf.ModdedWolfsConfigs.cfg to ModdedWolf.ModConfigs.cfg");
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Legacy config migration failed: " + ex.Message));
			}
		}

		private void TryMigrateLegacyShowMenuButton()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			try
			{
				ConfigDefinition val = new ConfigDefinition("General", "ShowMenuButton");
				if (((BaseUnityPlugin)this).Config.ContainsKey(val))
				{
					if (!((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowMenuButton", true, "Deprecated. Use ShowMainMenuButton / ShowPauseMenuButton.").Value)
					{
						ShowMainMenuButton.Value = false;
						ShowPauseMenuButton.Value = true;
					}
					((BaseUnityPlugin)this).Config.Remove(val);
					((BaseUnityPlugin)this).Config.Save();
				}
			}
			catch
			{
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	[HarmonyPatch(typeof(Menu), "Start")]
	internal static class Menu_Start_Patch
	{
		private static void Postfix()
		{
			PauseMenuButton.Refresh();
		}
	}
	[HarmonyPatch(typeof(Menu), "UpdateNavigation")]
	internal static class Menu_UpdateNavigation_Patch
	{
		private static void Postfix()
		{
			PauseMenuButton.Refresh();
		}
	}
	[HarmonyPatch(typeof(Menu), "OnSettings")]
	internal static class Menu_OnSettings_Patch
	{
		private static bool Prefix()
		{
			if (!PauseMenuButton.IsModConfigsControlActive())
			{
				return true;
			}
			ConfigPanelOpener.Open();
			return false;
		}
	}
	[HarmonyPatch(typeof(FejdStartup), "Start")]
	internal static class FejdStartup_Start_Patch
	{
		private static void Postfix()
		{
			PauseMenuButton.Refresh();
		}
	}
	[HarmonyPatch(typeof(FejdStartup), "SetupGui")]
	internal static class FejdStartup_SetupGui_Patch
	{
		private static void Postfix()
		{
			PauseMenuButton.Refresh();
		}
	}
	[HarmonyPatch(typeof(Settings), "OnDestroy")]
	internal static class Settings_OnDestroy_Patch
	{
		private static void Postfix(Settings __instance)
		{
			ConfigPanelOpener.ForgetInstance(__instance);
			ModConfigPanel.ForgetInitialized(__instance);
			PauseMenuButton.Refresh();
		}
	}
	internal static class SettingsConversionPatches
	{
		[HarmonyPatch(typeof(Settings), "Awake")]
		internal static class SettingsAwakePatch
		{
			private static void Prefix(Settings __instance)
			{
				if (ConfigPanelOpener.IsOpening)
				{
					ConfigPanelOpener.MarkInstance(__instance);
				}
			}

			private static void Postfix(Settings __instance)
			{
				if (ShouldConvert(__instance))
				{
					ModConfigPanel.ConvertSettingsInstance(__instance);
					ModConfigPanel.EnforceConvertedLayout(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(Settings), "InitializeTabs")]
		internal static class SettingsInitializeTabsPatch
		{
			private static bool Prefix(Settings __instance)
			{
				if (!ShouldConvert(__instance))
				{
					return true;
				}
				ConfigPanelOpener.MarkInstance(__instance);
				ModConfigPanel.ConvertSettingsInstance(__instance);
				ModConfigPanel.EnforceConvertedLayout(__instance);
				return false;
			}
		}

		[HarmonyPatch(typeof(Settings), "OnBack")]
		internal static class SettingsOnBackPatch
		{
			private static bool Prefix(Settings __instance)
			{
				if (ConfigPanelOpener.IsOurInstance(__instance) && KeybindCapture.TryCancelListen())
				{
					return false;
				}
				return HandleCloseIfBroken(__instance);
			}
		}

		[HarmonyPatch(typeof(Settings), "OnOk")]
		internal static class SettingsOnOkPatch
		{
			private static bool Prefix(Settings __instance)
			{
				return HandleCloseIfBroken(__instance);
			}
		}

		private static bool ShouldConvert(Settings settings)
		{
			if (!ConfigPanelOpener.IsOpening)
			{
				return ConfigPanelOpener.IsOurInstance(settings);
			}
			return true;
		}

		private static bool HandleCloseIfBroken(Settings settings)
		{
			if (!ConfigPanelOpener.IsOurInstance(settings))
			{
				return true;
			}
			List<ISettingsTab> settingsTabs = settings.SettingsTabs;
			if (settingsTabs != null && settingsTabs.Count > 0)
			{
				return true;
			}
			ForceClose(settings);
			return false;
		}

		private static void ForceClose(Settings settings)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)settings == (Object)null)
			{
				return;
			}
			try
			{
				if ((Object)(object)Menu.instance != (Object)null && (Object)(object)Menu.instance.m_settingsInstance == (Object)(object)((Component)settings).gameObject)
				{
					Menu.instance.m_settingsInstance = null;
					Menu.instance.m_closeMenuState = (CloseMenuState)2;
				}
				Object.Destroy((Object)(object)((Component)settings).gameObject);
			}
			catch (Exception ex)
			{
				ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to force-close Mod Configs: " + ex.Message));
			}
		}
	}
	internal static class ConfigPanelOpener
	{
		private static readonly HashSet<int> PendingInstanceIds = new HashSet<int>();

		internal static bool IsOpening { get; private set; }

		internal static void MarkInstance(Settings settings)
		{
			if (!((Object)(object)settings == (Object)null))
			{
				PendingInstanceIds.Add(((Object)settings).GetInstanceID());
			}
		}

		internal static bool IsOurInstance(Settings settings)
		{
			if ((Object)(object)settings == (Object)null)
			{
				return false;
			}
			return PendingInstanceIds.Contains(((Object)settings).GetInstanceID());
		}

		internal static void ForgetInstance(Settings settings)
		{
			if (!((Object)(object)settings == (Object)null))
			{
				PendingInstanceIds.Remove(((Object)settings).GetInstanceID());
			}
		}

		internal static void Open()
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)Settings.instance != (Object)null)
				{
					return;
				}
				GameObject val = FindSettingsPrefab();
				if ((Object)(object)val == (Object)null)
				{
					ModdedWolfsConfigsPlugin.Log.LogWarning((object)"Could not find Settings prefab (Menu / FejdStartup). Cannot open config panel.");
					return;
				}
				Transform val2 = null;
				if ((Object)(object)Menu.instance != (Object)null)
				{
					val2 = ((Component)Menu.instance).transform;
				}
				else if ((Object)(object)FejdStartup.instance != (Object)null)
				{
					val2 = ((Component)FejdStartup.instance).transform;
				}
				IsOpening = true;
				GameObject val3 = Object.Instantiate<GameObject>(val, val2);
				IsOpening = false;
				Settings val4 = (((Object)(object)val3 != (Object)null) ? val3.GetComponent<Settings>() : null);
				if ((Object)(object)val4 != (Object)null)
				{
					MarkInstance(val4);
					ModConfigPanel.ConvertSettingsInstance(val4);
					ModConfigPanel.EnforceConvertedLayout(val4);
				}
				if ((Object)(object)Menu.instance != (Object)null)
				{
					Menu.instance.m_settingsInstance = val3;
					Menu.instance.m_closeMenuState = (CloseMenuState)0;
				}
				ModdedWolfsConfigsPlugin.Log.LogInfo((object)"Opened ModdedWolf's Configs panel.");
			}
			catch (Exception arg)
			{
				IsOpening = false;
				ModdedWolfsConfigsPlugin.Log.LogWarning((object)$"Failed to open config panel: {arg}");
			}
		}

		private static GameObject FindSettingsPrefab()
		{
			if ((Object)(object)Menu.instance != (Object)null && (Object)(object)Menu.instance.m_settingsPrefab != (Object)null)
			{
				return Menu.instance.m_settingsPrefab;
			}
			if ((Object)(object)FejdStartup.instance != (Object)null && (Object)(object)FejdStartup.instance.m_settingsPrefab != (Object)null)
			{
				return FejdStartup.instance.m_settingsPrefab;
			}
			return null;
		}
	}
	internal sealed class KeybindCapture : MonoBehaviour
	{
		private ConfigEntryBase _entry;

		private TMP_Text _valueText;

		private Button _button;

		private bool _listening;

		private int _armFrame = -1;

		private Coroutine _savedFlash;

		private static KeybindCapture _active;

		private static readonly KeyCode[] ModifierKeys;

		internal static bool IsListening
		{
			get
			{
				if ((Object)(object)_active != (Object)null)
				{
					return _active._listening;
				}
				return false;
			}
		}

		internal static bool TryCancelListen()
		{
			if ((Object)(object)_active == (Object)null || !_active._listening)
			{
				return false;
			}
			_active.CancelListen();
			return true;
		}

		internal void Bind(ConfigEntryBase entry, Button button, TMP_Text valueText)
		{
			_entry = entry;
			_button = button;
			_valueText = valueText;
			RefreshLabel();
			WireButton(_button);
		}

		private void WireButton(Button button)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			if (!((Object)(object)button == (Object)null))
			{
				((UnityEventBase)button.onClick).RemoveAllListeners();
				((UnityEvent)button.onClick).AddListener(new UnityAction(BeginListen));
			}
		}

		private void OnDisable()
		{
			if (_savedFlash != null)
			{
				((MonoBehaviour)this).StopCoroutine(_savedFlash);
				_savedFlash = null;
			}
			if (_active == this)
			{
				_listening = false;
				_active = null;
			}
		}

		private void BeginListen()
		{
			if (_entry != null)
			{
				if ((Object)(object)_active != (Object)null && _active != this && _active._listening)
				{
					_active.CancelListen();
				}
				if (_savedFlash != null)
				{
					((MonoBehaviour)this).StopCoroutine(_savedFlash);
					_savedFlash = null;
				}
				_listening = true;
				_armFrame = Time.frameCount;
				_active = this;
				if ((Object)(object)_valueText != (Object)null)
				{
					_valueText.text = "Press key… (Esc cancel)";
				}
			}
		}

		private void CancelListen()
		{
			_listening = false;
			if (_active == this)
			{
				_active = null;
			}
			RefreshLabel();
		}

		private void Update()
		{
			//IL_0058: 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_005e: 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_0064: Invalid comparison between Unknown and I4
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Invalid comparison between Unknown and I4
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Invalid comparison between Unknown and I4
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Invalid comparison between Unknown and I4
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			if (!CanCapture())
			{
				return;
			}
			if (Input.GetKeyDown((KeyCode)27))
			{
				CancelListen();
				return;
			}
			for (int i = 2; i <= 6; i++)
			{
				if (Input.GetMouseButtonDown(i))
				{
					CommitKey((KeyCode)(323 + i));
					return;
				}
			}
			foreach (KeyCode value in Enum.GetValues(typeof(KeyCode)))
			{
				if ((int)value != 0 && (int)value != 27 && !IsModifier(value) && ((int)value < 323 || (int)value > 329) && (int)value < 330 && Input.GetKeyDown(value))
				{
					CommitKey(value);
					break;
				}
			}
		}

		private void OnGUI()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Invalid comparison between Unknown and I4
			//IL_003c: 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_0053: Invalid comparison between Unknown and I4
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Invalid comparison between Unknown and I4
			if (!CanCapture())
			{
				return;
			}
			Event current = Event.current;
			if (current == null)
			{
				return;
			}
			if ((int)current.type == 4 && (int)current.keyCode != 0)
			{
				if ((int)current.keyCode == 27)
				{
					CancelListen();
					current.Use();
				}
				else if (!IsModifier(current.keyCode) && ((int)current.keyCode < 323 || (int)current.keyCode > 329))
				{
					CommitKey(current.keyCode);
					current.Use();
				}
			}
			else if ((int)current.type == 0 && current.button >= 2 && current.button <= 6)
			{
				CommitKey((KeyCode)(323 + current.button));
				current.Use();
			}
		}

		private bool CanCapture()
		{
			if (_listening && _entry != null)
			{
				return Time.frameCount > _armFrame;
			}
			return false;
		}

		private void CommitKey(KeyCode main)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (_listening)
			{
				_listening = false;
				if (_active == this)
				{
					_active = null;
				}
				ApplyKey(main);
			}
		}

		private unsafe void ApplyKey(KeyCode main)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			Type settingType = _entry.SettingType;
			try
			{
				if (settingType == typeof(KeyboardShortcut))
				{
					List<KeyCode> list = new List<KeyCode>();
					for (int i = 0; i < ModifierKeys.Length; i++)
					{
						if (Input.GetKey(ModifierKeys[i]))
						{
							list.Add(ModifierKeys[i]);
						}
					}
					_entry.BoxedValue = (object)new KeyboardShortcut(main, list.ToArray());
				}
				else if (settingType == typeof(KeyCode))
				{
					_entry.BoxedValue = main;
				}
				else
				{
					_entry.SetSerializedValue(((object)(*(KeyCode*)(&main))/*cast due to .constrained prefix*/).ToString());
				}
				ConfigApply.PersistAfterLocalChange(_entry);
				ShowSavedFlash(FormatCurrentBind());
			}
			catch (Exception ex)
			{
				ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to set keybind: " + ex.Message));
				RefreshLabel();
			}
		}

		private void ShowSavedFlash(string bindLabel)
		{
			if ((Object)(object)_valueText == (Object)null)
			{
				RefreshLabel();
				return;
			}
			if (_savedFlash != null)
			{
				((MonoBehaviour)this).StopCoroutine(_savedFlash);
			}
			_savedFlash = ((MonoBehaviour)this).StartCoroutine(SavedFlashRoutine(bindLabel));
		}

		private IEnumerator SavedFlashRoutine(string bindLabel)
		{
			if ((Object)(object)_valueText != (Object)null)
			{
				_valueText.text = "Saved: " + bindLabel;
			}
			yield return (object)new WaitForSecondsRealtime(1f);
			_savedFlash = null;
			RefreshLabel();
		}

		private void RefreshLabel()
		{
			if (!((Object)(object)_valueText == (Object)null) && _entry != null)
			{
				_valueText.text = FormatCurrentBind();
			}
		}

		private unsafe string FormatCurrentBind()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			if (_entry == null)
			{
				return "None";
			}
			if (_entry.BoxedValue is KeyboardShortcut shortcut)
			{
				return FormatShortcut(shortcut);
			}
			if (_entry.BoxedValue is KeyCode val)
			{
				if ((int)val != 0)
				{
					return ((object)(*(KeyCode*)(&val))/*cast due to .constrained prefix*/).ToString();
				}
				return "None";
			}
			string text = _entry.GetSerializedValue();
			if (string.IsNullOrEmpty(text))
			{
				text = _entry.BoxedValue?.ToString() ?? "None";
			}
			return text;
		}

		private static string FormatShortcut(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0)
			{
				return "None";
			}
			StringBuilder stringBuilder = new StringBuilder();
			IEnumerable<KeyCode> modifiers = ((KeyboardShortcut)(ref shortcut)).Modifiers;
			if (modifiers != null)
			{
				foreach (KeyCode item in modifiers)
				{
					if (stringBuilder.Length > 0)
					{
						stringBuilder.Append('+');
					}
					stringBuilder.Append(item);
				}
			}
			if (stringBuilder.Length > 0)
			{
				stringBuilder.Append('+');
			}
			stringBuilder.Append(((KeyboardShortcut)(ref shortcut)).MainKey);
			return stringBuilder.ToString();
		}

		private static bool IsModifier(KeyCode key)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between I4 and Unknown
			for (int i = 0; i < ModifierKeys.Length; i++)
			{
				if ((int)ModifierKeys[i] == (int)key)
				{
					return true;
				}
			}
			return false;
		}

		static KeybindCapture()
		{
			KeyCode[] array = new KeyCode[8];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			ModifierKeys = (KeyCode[])(object)array;
		}
	}
	internal static class ModConfigPanel
	{
		private const string PageName = "ModdedWolfsConfigsPage";

		private static readonly HashSet<int> BodyReadyIds = new HashSet<int>();

		internal static void ConvertSettingsInstance(Settings settings)
		{
			try
			{
				if ((Object)(object)settings == (Object)null)
				{
					return;
				}
				Transform val = FindConvertedPage(settings);
				if ((Object)(object)val != (Object)null)
				{
					RenameTitle(settings);
					StripSettingsChrome(settings);
					DisableTabHandler(settings);
					HideTabStrip(settings);
					NeutralizeAccessibilityGuiScale(settings);
					HideVanillaSettingsPages(settings, ((Component)val).gameObject);
					EnsureSettingsTabs(settings, ((Component)val).GetComponent<ModConfigTab>());
					AttachLayoutLock(settings);
					EnforceConvertedLayout(settings);
					RestoreGuiScale();
					return;
				}
				RenameTitle(settings);
				StripSettingsChrome(settings);
				DisableTabHandler(settings);
				HideTabStrip(settings);
				NeutralizeAccessibilityGuiScale(settings);
				HideVanillaSettingsPages(settings, null);
				RectTransform val2 = CreateBodyPage(settings);
				if ((Object)(object)val2 == (Object)null)
				{
					ModdedWolfsConfigsPlugin.Log.LogWarning((object)"Could not find a parent for the Mod Configs body page.");
					RestoreGuiScale();
					return;
				}
				ModConfigTab modConfigTab = ((Component)val2).gameObject.AddComponent<ModConfigTab>();
				if (!modConfigTab.TryBuild(settings, val2))
				{
					Object.Destroy((Object)(object)((Component)val2).gameObject);
					ModdedWolfsConfigsPlugin.Log.LogWarning((object)"Failed to build ModdedWolf's Configs body UI.");
					RestoreGuiScale();
					return;
				}
				EnsureSettingsTabs(settings, modConfigTab);
				ActivatePageAndAncestors(((Component)val2).transform, ((Component)settings).transform);
				WireBodyNavigation(settings, modConfigTab);
				AttachLayoutLock(settings);
				EnforceConvertedLayout(settings);
				RestoreGuiScale();
				BodyReadyIds.Add(((Object)settings).GetInstanceID());
				ModdedWolfsConfigsPlugin.Log.LogInfo((object)"ModdedWolf's Configs body ready.");
			}
			catch (Exception arg)
			{
				RestoreGuiScale();
				ModdedWolfsConfigsPlugin.Log.LogWarning((object)$"Failed to convert Settings panel: {arg}");
			}
		}

		private static void NeutralizeAccessibilityGuiScale(Settings settings)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			if ((Object)(object)settings == (Object)null)
			{
				return;
			}
			AccessibilitySettings[] componentsInChildren = ((Component)settings).GetComponentsInChildren<AccessibilitySettings>(true);
			foreach (AccessibilitySettings val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					((Behaviour)val).enabled = false;
					if ((Object)(object)val.m_guiScaleSlider != (Object)null)
					{
						val.m_guiScaleSlider.onValueChanged = new SliderEvent();
					}
				}
			}
		}

		private static void RestoreGuiScale()
		{
			try
			{
				GuiScaler.SetScale(PlatformPrefs.GetFloat("GuiScale", 1f));
			}
			catch (Exception ex)
			{
				ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to restore GUI scale: " + ex.Message));
			}
		}

		internal static void ForgetInitialized(Settings settings)
		{
			if (!((Object)(object)settings == (Object)null))
			{
				BodyReadyIds.Remove(((Object)settings).GetInstanceID());
			}
		}

		internal static void EnforceConvertedLayout(Settings settings)
		{
			if ((Object)(object)settings == (Object)null)
			{
				return;
			}
			Transform val = FindConvertedPage(settings);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			try
			{
				RenameTitle(settings);
				StripSettingsChrome(settings);
				DisableTabHandler(settings);
				HideTabStrip(settings);
				HideVanillaSettingsPages(settings, ((Component)val).gameObject);
				ActivatePageAndAncestors(val, ((Component)settings).transform);
			}
			catch (Exception ex)
			{
				ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to enforce Mod Configs layout: " + ex.Message));
			}
		}

		private static void EnsureSettingsTabs(Settings settings, ModConfigTab modTab)
		{
			if (!((Object)(object)settings == (Object)null) && !((Object)(object)modTab == (Object)null) && (settings.SettingsTabs == null || settings.SettingsTabs.Count != 1 || (object)settings.SettingsTabs[0] != modTab))
			{
				settings.SettingsTabs = new List<ISettingsTab> { (ISettingsTab)(object)modTab };
			}
		}

		private static void AttachLayoutLock(Settings settings)
		{
			if ((Object)(object)((Component)settings).GetComponent<ModConfigLayoutLock>() == (Object)null)
			{
				((Component)settings).gameObject.AddComponent<ModConfigLayoutLock>();
			}
		}

		private static void DisableTabHandler(Settings settings)
		{
			TabHandler val = (((Object)(object)settings.m_tabHandler != (Object)null) ? settings.m_tabHandler : ((Component)settings).GetComponentInChildren<TabHandler>(true));
			if (!((Object)(object)val == (Object)null))
			{
				settings.m_tabHandler = val;
				((Behaviour)val).enabled = false;
				val.m_tabKeyInput = false;
				val.m_keybaordInput = false;
				val.m_gamepadInput = false;
			}
		}

		private static void HideTabStrip(Settings settings)
		{
			TabHandler val = (((Object)(object)settings.m_tabHandler != (Object)null) ? settings.m_tabHandler : ((Component)settings).GetComponentInChildren<TabHandler>(true));
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Transform transform = ((Component)val).transform;
			if (val.m_tabs == null)
			{
				return;
			}
			for (int i = 0; i < val.m_tabs.Count; i++)
			{
				Tab val2 = val.m_tabs[i];
				if (!((Object)(object)val2?.m_button == (Object)null))
				{
					Transform val3 = FindTabRoot(((Component)val2.m_button).transform, transform);
					if ((Object)(object)val3 == (Object)null)
					{
						((Component)val2.m_button).gameObject.SetActive(false);
					}
					else if (!(((Object)val3).name == "ModdedWolfsConfigsPage") && !IsUnderModConfigPage(val3) && (!((Object)(object)settings.m_settingsPanel != (Object)null) || !((Object)(object)((Component)val3).gameObject == (Object)(object)settings.m_settingsPanel)) && (!((Object)(object)settings.m_backButton != (Object)null) || !((Object)(object)((Component)val3).gameObject == (Object)(object)((Component)settings.m_backButton).gameObject)) && (!((Object)(object)settings.m_okButton != (Object)null) || !((Object)(object)((Component)val3).gameObject == (Object)(object)((Component)settings.m_okButton).gameObject)))
					{
						((Component)val3).gameObject.SetActive(false);
					}
				}
			}
		}

		private static Transform FindTabRoot(Transform buttonTransform, Transform tabHandlerTransform)
		{
			Transform val = buttonTransform;
			Transform result = buttonTransform;
			while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)tabHandlerTransform)
			{
				result = val;
				if ((Object)(object)val.parent == (Object)(object)tabHandlerTransform)
				{
					return val;
				}
				val = val.parent;
			}
			return result;
		}

		private static void HideVanillaSettingsPages(Settings settings, GameObject keepPage)
		{
			MonoBehaviour[] componentsInChildren = ((Component)settings).GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !(val is ModConfigTab) && val is ISettingsTab)
				{
					((Behaviour)val).enabled = false;
					if ((!((Object)(object)keepPage != (Object)null) || !((Object)(object)((Component)val).gameObject == (Object)(object)keepPage)) && (!((Object)(object)settings.m_settingsPanel != (Object)null) || !((Object)(object)((Component)val).gameObject == (Object)(object)settings.m_settingsPanel)) && (!((Object)(object)settings.m_backButton != (Object)null) || !((Object)(object)((Component)val).gameObject == (Object)(object)((Component)settings.m_backButton).gameObject)) && (!((Object)(object)settings.m_okButton != (Object)null) || !((Object)(object)((Component)val).gameObject == (Object)(object)((Component)settings.m_okButton).gameObject)) && (!((Object)(object)keepPage != (Object)null) || !IsAncestorOf(((Component)val).transform, keepPage.transform)))
					{
						((Component)val).gameObject.SetActive(false);
					}
				}
			}
		}

		private static bool IsAncestorOf(Transform candidate, Transform descendant)
		{
			if ((Object)(object)candidate == (Object)null || (Object)(object)descendant == (Object)null)
			{
				return false;
			}
			Transform val = descendant;
			while ((Object)(object)val != (Object)null)
			{
				if ((Object)(object)val == (Object)(object)candidate)
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		private static RectTransform CreateBodyPage(Settings settings)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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)
			RectTransform val = FindTemplateTabPage(settings);
			if ((Object)(object)val == (Object)null || (Object)(object)((Transform)val).parent == (Object)null)
			{
				ModdedWolfsConfigsPlugin.Log.LogWarning((object)"No vanilla settings tab page template; cannot size Mod Configs body.");
				return null;
			}
			GameObject val2 = new GameObject("ModdedWolfsConfigsPage", new Type[1] { typeof(RectTransform) });
			val2.transform.SetParent(((Transform)val).parent, false);
			RectTransform component = val2.GetComponent<RectTransform>();
			component.anchorMin = val.anchorMin;
			component.anchorMax = val.anchorMax;
			component.pivot = val.pivot;
			component.anchoredPosition = val.anchoredPosition;
			component.sizeDelta = val.sizeDelta;
			component.offsetMin = val.offsetMin;
			component.offsetMax = val.offsetMax;
			((Transform)component).localScale = ((Transform)val).localScale;
			int num = CopyNativePageChrome(val, component);
			ModdedWolfsConfigsPlugin.Log.LogInfo((object)$"Mod Configs inner frame: copied {num} chrome piece(s) from '{((Object)val).name}'.");
			val2.SetActive(true);
			return component;
		}

		private static int CopyNativePageChrome(RectTransform template, RectTransform dest)
		{
			if ((Object)(object)template == (Object)null || (Object)(object)dest == (Object)null)
			{
				return 0;
			}
			int num = 0;
			Image component = ((Component)template).GetComponent<Image>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.sprite != (Object)null)
			{
				CopyImageComponent(component, ((Component)dest).gameObject);
				num++;
			}
			num += CopyGraphicEffect<Outline>(((Component)template).gameObject, ((Component)dest).gameObject);
			num += CopyGraphicEffect<Shadow>(((Component)template).gameObject, ((Component)dest).gameObject);
			int num2 = 0;
			for (int i = 0; i < ((Transform)template).childCount; i++)
			{
				Transform child = ((Transform)template).GetChild(i);
				if (LooksLikeChrome(child))
				{
					GameObject obj = Object.Instantiate<GameObject>(((Component)child).gameObject, (Transform)(object)dest, false);
					((Object)obj).name = ((Object)child).name;
					StripInteractiveChrome(obj);
					obj.SetActive(true);
					obj.transform.SetAsFirstSibling();
					num++;
					num2++;
				}
			}
			Image component2 = ((Component)dest).GetComponent<Image>();
			if ((!((Object)(object)component2 != (Object)null) || !((Object)(object)component2.sprite != (Object)null)) && num2 <= 0)
			{
				Image val = FindLargestDecorativeImage((Transform)(object)template);
				if ((Object)(object)val != (Object)null)
				{
					AddStretchedChromeImage(dest, val, "PageChrome");
					num++;
				}
			}
			return num;
		}

		private static bool LooksLikeChrome(Transform t)
		{
			if ((Object)(object)t == (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)t).GetComponentInChildren<Selectable>(true) != (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)t).GetComponentInChildren<TMP_Text>(true) != (Object)null)
			{
				return false;
			}
			if (NameLooksLikeFrame(((Object)t).name ?? string.Empty))
			{
				return true;
			}
			if (!((Object)(object)((Component)t).GetComponent<Image>() != (Object)null) && !((Object)(object)((Component)t).GetComponent<RawImage>() != (Object)null))
			{
				return ((Component)t).GetComponentsInChildren<Image>(true).Length != 0;
			}
			return true;
		}

		private static bool NameLooksLikeFrame(string n)
		{
			if (n.IndexOf("border", StringComparison.OrdinalIgnoreCase) < 0 && n.IndexOf("frame", StringComparison.OrdinalIgnoreCase) < 0 && n.IndexOf("bkg", StringComparison.OrdinalIgnoreCase) < 0 && n.IndexOf("background", StringComparison.OrdinalIgnoreCase) < 0 && n.IndexOf("deco", StringComparison.OrdinalIgnoreCase) < 0 && n.IndexOf("ornament", StringComparison.OrdinalIgnoreCase) < 0 && n.IndexOf("edge", StringComparison.OrdinalIgnoreCase) < 0 && n.IndexOf("well", StringComparison.OrdinalIgnoreCase) < 0 && n.IndexOf("chrome", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return n.IndexOf("panel", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private static Image FindLargestDecorativeImage(Transform root)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Invalid comparison between Unknown and I4
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Invalid comparison between Unknown and I4
			Image[] componentsInChildren = ((Component)root).GetComponentsInChildren<Image>(true);
			Image result = null;
			float num = 0f;
			foreach (Image val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.sprite == (Object)null || (Object)(object)((Component)val).GetComponent<Selectable>() != (Object)null)
				{
					continue;
				}
				Selectable componentInParent = ((Component)val).GetComponentInParent<Selectable>();
				if ((Object)(object)componentInParent != (Object)null && (Object)(object)((Component)componentInParent).transform != (Object)(object)root)
				{
					continue;
				}
				Rect rect = ((Graphic)val).rectTransform.rect;
				float num2 = Mathf.Abs(((Rect)(ref rect)).width * ((Rect)(ref rect)).height);
				if (!(num2 < 64f))
				{
					float num3 = num2;
					if ((int)val.type == 1 || (int)val.type == 2)
					{
						num3 *= 3f;
					}
					if (num3 > num)
					{
						num = num3;
						result = val;
					}
				}
			}
			return result;
		}

		private static void AddStretchedChromeImage(RectTransform dest, Image source, string name)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			val.transform.SetParent((Transform)(object)dest, false);
			val.transform.SetAsFirstSibling();
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = Vector2.zero;
			component.offsetMax = Vector2.zero;
			CopyImageComponent(source, val);
		}

		private static void CopyImageComponent(Image source, GameObject dest)
		{
			//IL_003d: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)source == (Object)null) && !((Object)(object)dest == (Object)null))
			{
				Image obj = dest.GetComponent<Image>() ?? dest.AddComponent<Image>();
				obj.sprite = source.sprite;
				obj.overrideSprite = source.overrideSprite;
				obj.type = source.type;
				((Graphic)obj).color = ((Graphic)source).color;
				obj.fillCenter = source.fillCenter;
				obj.pixelsPerUnitMultiplier = source.pixelsPerUnitMultiplier;
				((Graphic)obj).material = ((Graphic)source).material;
				((Graphic)obj).raycastTarget = false;
				((MaskableGraphic)obj).maskable = ((MaskableGraphic)source).maskable;
				obj.preserveAspect = source.preserveAspect;
				obj.fillMethod = source.fillMethod;
				obj.fillAmount = source.fillAmount;
			}
		}

		private static int CopyGraphicEffect<T>(GameObject source, GameObject dest) where T : Shadow
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			T component = source.GetComponent<T>();
			if ((Object)(object)component == (Object)null)
			{
				return 0;
			}
			T obj = dest.GetComponent<T>() ?? dest.AddComponent<T>();
			((Shadow)obj).effectColor = ((Shadow)component).effectColor;
			((Shadow)obj).effectDistance = ((Shadow)component).effectDistance;
			((Shadow)obj).useGraphicAlpha = ((Shadow)component).useGraphicAlpha;
			return 1;
		}

		private static void StripInteractiveChrome(GameObject go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return;
			}
			Selectable[] componentsInChildren = go.GetComponentsInChildren<Selectable>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null)
				{
					((Behaviour)componentsInChildren[i]).enabled = false;
				}
			}
			ScrollRect[] componentsInChildren2 = go.GetComponentsInChildren<ScrollRect>(true);
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				if ((Object)(object)componentsInChildren2[j] != (Object)null)
				{
					((Behaviour)componentsInChildren2[j]).enabled = false;
				}
			}
			TMP_Text[] componentsInChildren3 = go.GetComponentsInChildren<TMP_Text>(true);
			for (int k = 0; k < componentsInChildren3.Length; k++)
			{
				if ((Object)(object)componentsInChildren3[k] != (Object)null)
				{
					((Component)componentsInChildren3[k]).gameObject.SetActive(false);
				}
			}
		}

		private static RectTransform FindTemplateTabPage(Settings settings)
		{
			TabHandler val = (((Object)(object)settings.m_tabHandler != (Object)null) ? settings.m_tabHandler : ((Component)settings).GetComponentInChildren<TabHandler>(true));
			if (val?.m_tabs == null)
			{
				return null;
			}
			for (int i = 0; i < val.m_tabs.Count; i++)
			{
				Tab val2 = val.m_tabs[i];
				if ((Object)(object)val2?.m_page != (Object)null)
				{
					return val2.m_page;
				}
			}
			return null;
		}

		private static void ActivatePageAndAncestors(Transform page, Transform stopAt)
		{
			if ((Object)(object)page == (Object)null)
			{
				return;
			}
			Transform val = page;
			while ((Object)(object)val != (Object)null)
			{
				if (!((Component)val).gameObject.activeSelf)
				{
					((Component)val).gameObject.SetActive(true);
				}
				if (!((Object)(object)stopAt != (Object)null) || !((Object)(object)val == (Object)(object)stopAt))
				{
					val = val.parent;
					continue;
				}
				break;
			}
		}

		private static void WireBodyNavigation(Settings settings, ModConfigTab modTab)
		{
			if ((Object)(object)settings == (Object)null || (Object)(object)modTab == (Object)null)
			{
				return;
			}
			try
			{
				modTab.Initialize();
				modTab.OnTabOpen(settings.m_backButton, settings.m_okButton);
			}
			catch (Exception ex)
			{
				ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to wire Mod Configs navigation: " + ex.Message));
			}
		}

		private static Transform FindConvertedPage(Settings settings)
		{
			Transform[] componentsInChildren = ((Component)settings).GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null && ((Object)componentsInChildren[i]).name == "ModdedWolfsConfigsPage")
				{
					return componentsInChildren[i];
				}
			}
			return null;
		}

		internal static void StripSettingsChrome(Settings settings)
		{
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Invalid comparison between Unknown and I4
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Invalid comparison between Unknown and I4
			if ((Object)(object)settings == (Object)null)
			{
				return;
			}
			if (settings.m_tabKeyHints != null)
			{
				for (int i = 0; i < settings.m_tabKeyHints.Length; i++)
				{
					if ((Object)(object)settings.m_tabKeyHints[i] != (Object)null)
					{
						settings.m_tabKeyHints[i].SetActive(false);
					}
				}
			}
			TabHandler val = (((Object)(object)settings.m_tabHandler != (Object)null) ? settings.m_tabHandler : ((Component)settings).GetComponentInChildren<TabHandler>(true));
			if ((Object)(object)val != (Object)null)
			{
				val.m_tabKeyInput = false;
				val.m_keybaordInput = false;
				val.m_gamepadInput = false;
			}
			TMP_Text[] componentsInChildren = ((Component)settings).GetComponentsInChildren<TMP_Text>(true);
			foreach (TMP_Text val2 in componentsInChildren)
			{
				if ((Object)(object)val2 == (Object)null || IsUnderModConfigPage(val2.transform))
				{
					continue;
				}
				string text = ((val2.text != null) ? val2.text.Trim() : string.Empty);
				if (text.Length == 1)
				{
					char c = char.ToUpperInvariant(text[0]);
					if (c == 'Q' || c == 'E')
					{
						((Component)val2).gameObject.SetActive(false);
					}
				}
			}
			UIGamePad[] componentsInChildren2 = ((Component)settings).GetComponentsInChildren<UIGamePad>(true);
			foreach (UIGamePad val3 in componentsInChildren2)
			{
				if (!((Object)(object)val3 == (Object)null) && (val3.m_zinputKey == "TabLeft" || val3.m_zinputKey == "TabRight" || (int)val3.m_keyCode == 113 || (int)val3.m_keyCode == 101 || ((Object)(object)val3.m_hint != (Object)null && IsLikelyTabHintObject(val3.m_hint))))
				{
					if ((Object)(object)val3.m_hint != (Object)null)
					{
						val3.m_hint.SetActive(false);
					}
					((Behaviour)val3).enabled = false;
				}
			}
		}

		private static bool IsUnderModConfigPage(Transform t)
		{
			while ((Object)(object)t != (Object)null)
			{
				if (((Object)t).name == "ModdedWolfsConfigsPage")
				{
					return true;
				}
				t = t.parent;
			}
			return false;
		}

		private static bool IsLikelyTabHintObject(GameObject go)
		{
			if ((Object)(object)go == (Object)null)
			{
				return false;
			}
			string name = ((Object)go).name;
			if (name.IndexOf("hint", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Tab", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return name.IndexOf("key", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private static void RenameTitle(Settings settings)
		{
			Transform[] array = (Transform[])(object)new Transform[5]
			{
				((Component)settings).transform.Find("panel/Title"),
				((Component)settings).transform.Find("Panel/Title"),
				((Component)settings).transform.Find("Title"),
				((Component)settings).transform.Find("panel/Header"),
				((Component)settings).transform.Find("Panel/Header")
			};
			for (int i = 0; i < array.Length; i++)
			{
				if (!((Object)(object)array[i] == (Object)null))
				{
					TMP_Text componentInChildren = ((Component)array[i]).GetComponentInChildren<TMP_Text>(true);
					if ((Object)(object)componentInChildren != (Object)null)
					{
						componentInChildren.text = "Mod Configs";
						return;
					}
				}
			}
			TMP_Text[] componentsInChildren = ((Component)settings).GetComponentsInChildren<TMP_Text>(true);
			for (int j = 0; j < componentsInChildren.Length; j++)
			{
				string text = componentsInChildren[j].text;
				if (!string.IsNullOrEmpty(text) && (text.Equals("Settings", StringComparison.OrdinalIgnoreCase) || (text.IndexOf("settings", StringComparison.OrdinalIgnoreCase) >= 0 && text.Length < 24)) && (componentsInChildren[j].fontSize >= 24f || (Object)(object)componentsInChildren[j].transform.parent == (Object)(object)((Component)settings).transform || ((Object)(object)componentsInChildren[j].transform.parent != (Object)null && ((Object)componentsInChildren[j].transform.parent).name.IndexOf("title", StringComparison.OrdinalIgnoreCase) >= 0) || ((Object)(object)componentsInChildren[j].transform.parent != (Object)null && ((Object)componentsInChildren[j].transform.parent).name.IndexOf("header", StringComparison.OrdinalIgnoreCase) >= 0)))
				{
					componentsInChildren[j].text = "Mod Configs";
					return;
				}
			}
			TMP_Text val = null;
			float num = 0f;
			for (int k = 0; k < componentsInChildren.Length; k++)
			{
				if (componentsInChildren[k].fontSize > num)
				{
					num = componentsInChildren[k].fontSize;
					val = componentsInChildren[k];
				}
			}
			if ((Object)(object)val != (Object)null && num >= 22f)
			{
				val.text = "Mod Configs";
			}
		}
	}
	internal sealed class ModConfigLayoutLock : MonoBehaviour
	{
		private Settings _settings;

		private int _framesRemaining = 120;

		private void Awake()
		{
			_settings = ((Component)this).GetComponent<Settings>();
		}

		private void LateUpdate()
		{
			if ((Object)(object)_settings == (Object)null)
			{
				_settings = ((Component)this).GetComponent<Settings>();
			}
			if ((Object)(object)_settings == (Object)null)
			{
				((Behaviour)this).enabled = false;
				return;
			}
			ModConfigPanel.EnforceConvertedLayout(_settings);
			if (--_framesRemaining <= 0)
			{
				((Behaviour)this).enabled = false;
			}
		}
	}
	internal sealed class ModConfigTab : MonoBehaviour, ISettingsTab
	{
		private Settings _settings;

		private Transform _content;

		private Transform _pinnedHeader;

		private ModPicker _modPicker;

		private Button _resetDefaultsButton;

		private GuiInputField _settingsSearchField;

		private string _settingsSearchQuery = string.Empty;

		private TMP_Text _labelTemplate;

		private Toggle _toggleTemplate;

		private Slider _sliderTemplate;

		private GuiDropdown _dropdownTemplate;

		private GuiInputField _inputFieldTemplate;

		private Button _buttonTemplate;

		private List<DiscoveredPlugin> _plugins = new List<DiscoveredPlugin>();

		private readonly List<Selectable> _selectables = new List<Selectable>();

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

		private int _selectedModIndex;

		private static ModConfigTab _openInstance;

		public event Action<string, int> SharedSettingChanged;

		internal static void RefreshOpenInstance()
		{
			if ((Object)(object)_openInstance == (Object)null || !((Behaviour)_openInstance).isActiveAndEnabled)
			{
				return;
			}
			try
			{
				_openInstance.RebuildSelectedModUi();
			}
			catch (Exception ex)
			{
				ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Failed to refresh config UI: " + ex.Message));
			}
		}

		private void OnEnable()
		{
			_openInstance = this;
		}

		private void OnDisable()
		{
			if (_openInstance == this)
			{
				_openInstance = null;
			}
		}

		internal bool TryBuild(Settings settings, RectTransform page)
		{
			_settings = settings;
			_dropdownTemplate = NativeWidgetFactory.FindDropdownTemplate(settings);
			_sliderTemplate = NativeWidgetFactory.FindSliderTemplate(settings);
			_toggleTemplate = NativeWidgetFactory.FindToggleTemplate(settings);
			_buttonTemplate = NativeWidgetFactory.FindButtonTemplate(settings);
			_inputFieldTemplate = NativeWidgetFactory.FindInputFieldTemplate(settings);
			_labelTemplate = NativeWidgetFactory.FindLabelTemplate(settings, _toggleTemplate, _sliderTemplate);
			if ((Object)(object)_dropdownTemplate == (Object)null && (Object)(object)_toggleTemplate == (Object)null && (Object)(object)_sliderTemplate == (Object)null && (Object)(object)_buttonTemplate == (Object)null)
			{
				ModdedWolfsConfigsPlugin.Log.LogWarning((object)"No native widget templates found.");
				return false;
			}
			ModdedWolfsConfigsPlugin.Log.LogInfo((object)($"Widget templates: dropdown={(Object)(object)_dropdownTemplate != (Object)null}, toggle={(Object)(object)_toggleTemplate != (Object)null}, " + $"slider={(Object)(object)_sliderTemplate != (Object)null}, button={(Object)(object)_buttonTemplate != (Object)null}, " + $"input={(Object)(object)_inputFieldTemplate != (Object)null}"));
			_pinnedHeader = NativeWidgetFactory.CreatePinnedHeader(page, 115f);
			NativeWidgetFactory.CreateScrollableContent(page, out _content, 135f);
			_plugins = DiscoverOrEmpty();
			RestoreSelectedModIndex();
			BuildModSelector();
			RebuildSelectedModUi();
			return true;
		}

		public void Initialize()
		{
			_plugins = DiscoverOrEmpty();
			RestoreSelectedModIndex();
			RefreshModDropdownOptions();
			RebuildSelectedModUi();
		}

		private static List<DiscoveredPlugin> DiscoverOrEmpty()
		{
			try
			{
				return ConfigDiscovery.Discover() ?? new List<DiscoveredPlugin>();
			}
			catch (Exception ex)
			{
				ModdedWolfsConfigsPlugin.Log.LogWarning((object)("Config discovery failed; showing empty mod list: " + ex.Message));
				return new List<DiscoveredPlugin>();
			}
		}

		public void OnTabOpen(Button backButton, Button okButton)
		{
			try
			{
				ModConfigPanel.StripSettingsChrome(_settings);
				RebuildSelectedModUi();
				Selectable val = (Selectable)((_selectables.Count > 0) ? _selectables[_selectables.Count - 1] : (((Object)(object)_modPicker != (Object)null) ? ((object)_modPicker.Selectable) : ((object)_resetDefaultsButton)));
				if (!((Object)(object)val == (Object)null))
				{
					if ((Object)(object)backButton != (Object)null)
					{
						GuiUtils.SetNavigationDown(val, (Selectable)(object)backButton);
						GuiUtils.SetNavigationUp((Selectable)(object)backButton, val);
					}
					if ((Object)(object)okButton != (Object)null)
					{
						GuiUtils.SetNavigationUp((Selectable)(object)okButton, val);
					}
				}
			}
			catch (Exception ex)
			{
				ModdedWolfsConfigsPlugin.Log.LogWarning((object)("OnTabOpen failed: " + ex.Message));
			}
		}

		public void OnOkAsync(OkActionCompletedHandler okActionCompletedCallback)
		{
			if (okActionCompletedCallback != null)
			{
				okActionCompletedCallback.Invoke();
			}
		}

		public void OnBack()
		{
		}

		public void OnSharedSettingChanged(string setting, int value)
		{
		}

		public void Terminate()
		{
		}

		private void BuildModSelector()
		{
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Expected O, but got Unknown
			Transform val = (((Object)(object)_pinnedHeader != (Object)null) ? _pinnedHeader : _content);
			if ((Object)(object)val == (Object)null)
			{
				ModdedWolfsConfigsPlugin.Log.LogWarning((object)"Mod picker skipped — missing header parent.");
				return;
			}
			List<string> list = BuildModOptionNames();
			_selectedModIndex = Mathf.Clamp(_selectedModIndex, 0, Mathf.Max(0, list.Count - 1));
			Transform val2 = NativeWidgetFactory.CreateRow(val, "ModAndReset");
			_modPicker = ModPicker.Create(val2, _buttonTemplate, _labelTemplate, null, list, _selectedModIndex, OnModChanged, _inputFieldTemplate, _dropdownTemplate, useParentAsRow: true, enableSearch: true, "Search mods...", "(No mod configs found)");
			if ((Object)(object)_modPicker?.Selectable != (Object)null)
			{
				_selectables.Add(_modPicker.Selectable);
			}
			_resetDefaultsButton = NativeWidgetFactory.CreateInlineButton(val2, _buttonTemplate, "Reset to Defaults", 180f);
			if ((Object)(object)_resetDefaultsButton == (Object)null)
			{
				_resetDefaultsButton = NativeWidgetFactory.CreateStepButton(val2, _buttonTemplate, "Reset to Defaults");
			}
			if ((Object)(object)_resetDefaultsButton != (Object)null)
			{
				LayoutElement component = ((Component)_resetDefaultsButton).GetComponent<LayoutElement>();
				if ((Object)(object)component != (Object)null)
				{
					component.flexibleWidth = 0f;
				}
				((UnityEventBase)_resetDefaultsButton.onClick).RemoveAllListeners();
				((UnityEvent)_resetDefaultsButton.onClick).AddListener(new UnityAction(ResetSelectedModToDefaults));
				_selectables.Add((Selectable)(object)_resetDefaultsButton);
			}
			Transform row = NativeWidgetFactory.CreateRow(val, "SettingsSearch");
			_settingsSearchField = NativeWidgetFactory.CreateSearchField(row, _inputFieldTemplate, "Search settings...", OnSettingsSearchChanged);
			if ((Object)(object)_settingsSearchField != (Object)null)
			{
				_selectables.Add((Selectable)(object)_settingsSearchField);
			}
			ModdedWolfsConfigsPlugin.Log.LogInfo((object)$"Mod picker ready with {_plugins.Count} mod(s).");
		}

		private void OnSettingsSearchChanged(string value)
		{
			_settingsSearchQuery = value ?? string.Empty;
			RebuildSelectedModUi();
		}

		private void ClearSettingsSearch()
		{
			_settingsSearchQuery = string.Empty;
			if ((Object)(object)_settingsSearchField != (Object)null)
			{
				NativeWidgetFactory.SetInputFieldText(_settingsSearchField, string.Empty);
			}
		}

		private List<string> BuildModOptionNames()
		{
			List<string> list = new List<string>();
			for (int i = 0; i < _plugins.Count; i++)
			{
				list.Add(_plugins[i].Name + " " + _plugins[i].Version);
			}
			if (list.Count == 0)
			{
				list.Add("(No mod configs found)");
			}
			return list;
		}

		private void RefreshModDropdownOptions()
		{
			if (!((Object)(object)_modPicker == (Object)null))
			{
				List<string> list = BuildModOptionNames();
				_selectedModIndex = Mathf.Clamp(_selectedModIndex, 0, Mathf.Max(0, list.Count - 1));
				_modPicker.SetOptions(list, _selectedModIndex);
			}
		}

		private void OnModChanged(int index)
		{
			ClearSettingsSearch();
			_selectedModIndex = index;
			PersistSelectedModGuid();
			RebuildSelectedModUi();
		}

		private int IndexForSavedModGuid()
		{
			string text = ModdedWolfsConfigsPlugin.LastSelectedModGuid?.Value;
			if (string.IsNullOrEmpty(text))
			{
				return -1;
			}
			for (int i = 0; i < _plugins.Count; i++)
			{
				if (string.Equals(_plugins[i].Guid, text, StringComparison.OrdinalIgnoreCase))
				{
					return i;
				}
			}
			return -1;
		}

		private void RestoreSelectedModIndex()
		{
			if (_plugins.Count == 0)
			{
				_selectedModIndex = 0;
				return;
			}
			ConfigEntry<bool> rememberLastMod = ModdedWolfsConfigsPlugin.RememberLastMod;
			if (rememberLastMod != null && rememberLastMod.Value)
			{
				int num = IndexForSavedModGuid();
				if (num >= 0)
				{
					_selectedModIndex = num;
					return;
				}
			}
			_selectedModIndex = Mathf.Clamp(_selectedModIndex, 0, _plugins.Count - 1);
		}

		private void PersistSelectedModGuid()
		{
			ConfigEntry<bool> rememberLastMod = ModdedWolfsConfigsPlugin.RememberLastMod;
			if (rememberLastMod == null || !rememberLastMod.Value || _plugins.Count == 0 || _selectedModIndex < 0 || _selectedModIndex >= _plugins.Count)
			{
				return;
			}
			ModdedWolfsConfigsPlugin.LastSelectedModGuid.Value = _plugins[_selectedModIndex].Guid;
			ModdedWolfsConfigsPlugin instance = ModdedWolfsConfigsPlugin.Instance;
			if (instance != null)
			{
				ConfigFile config = ((BaseUnityPlugin)instance).Config;
				if (config != null)
				{
					config.Save();
				}
			}
		}

		private void PersistRememberedModGuid(int index)
		{
			if (_plugins.Count == 0 || index < 0 || index >= _plugins.Count)
			{
				return;
			}
			ModdedWolfsConfigsPlugin.LastSelectedModGuid.Value = _plugins[index].Guid;
			ModdedWolfsConfigsPlugin instance = ModdedWolfsConfigsPlugin.Instance;
			if (instance != null)
			{
				ConfigFile config = ((BaseUnityPlugin)instance).Config;
				if (config != null)
				{
					config.Save();
				}
			}
		}

		private void ResetSelectedModToDefaults()
		{
			if (_plugins.Count == 0 || _selectedModIndex < 0 || _selectedModIndex >= _plugins.Count)
			{
				return;
			}
			DiscoveredPlugin discoveredPlugin = _plugins[_selectedModIndex];
			int num = 0;
			for (int i = 0; i < discoveredPlugin.Sections.Count; i++)
			{
				DiscoveredSection discoveredSection = discoveredPlugin.Sections[i];
				for (int j = 0; j < discoveredSection.Entries.Count; j++)
				{
					ConfigEntryBase val = discoveredSection.Entries[j];
					if (val == null)
					{
						continue;
					}
					try
					{
						object defaultValue = val.DefaultValue;
						if (defaultValue != null || val.SettingType.IsClass || Nullable.GetUnderlyingType(val.SettingType) != null)
						{
							val.BoxedValue = defaultValue;
						}
						else
						{
							val.BoxedValue = Activator.CreateInstance(val.SettingType);
						}
						Save(val);
						num++;
					}
					catch (Exception ex)
					{
						ModdedWolfsConfigsPlugin.Log.LogWarning((object)$"Reset failed for {val.Definition}: {ex.Message}");
					}
				}
			}
			ModdedWolfsConfigsPlugin.Log.LogInfo((object)$"Reset {num} setting(s) to defaults for {discoveredPlugin.Name}.");
			RebuildSelectedModUi();
		}

		private void RebuildSelectedModUi()
		{
			ClearDynamicRows();
			_selectables.Clear();
			if ((Object)(object)_modPicker?.Selectable != (Object)null)
			{
				_selectables.Add(_modPicker.Selectable);
			}
			if ((Object)(object)_resetDefaultsButton != (Object)null)
			{
				_selectables.Add((Selectable)(object)_resetDefaultsButton);
			}
			if ((Object)(object)_settingsSearchField != (Object)null)
			{
				_selectables.Add((Selectable)(object)_settingsSearchField);
			}
			if (_plugins.Count == 0 || _selectedModIndex < 0 || _selectedModIndex >= _plugins.Count)
			{
				TMP_Text val = NativeWidgetFactory.CreateSectionHeader(_content, _labelTemplate, "No configurable mods loaded.");
				if ((Object)(object)val != (Object)null)
				{
					_dynamicRows.Add(((Component)val).gameObject);
				}
				return;
			}
			DiscoveredPlugin discoveredPlugin = _plugins[_selectedModIndex];
			string text = (_settingsSearchQuery ?? string.Empty).Trim();
			bool flag = text.Length > 0;
			int num = 0;
			for (int i = 0; i < discoveredPlugin.Sections.Count; i++)
			{
				DiscoveredSection discoveredSection = discoveredPlugin.Sections[i];
				List<ConfigEntryBase> list = new List<ConfigEntryBase>();
				for (int j = 0; j < discoveredSection.Entries.Count; j++)
				{
					ConfigEntryBase val2 = discoveredSection.Entries[j];
					if (ConfigDiscovery.ShouldRenderEntry(val2) && (!IsOwnPluginGeneralSection(discoveredPlugin, discoveredSection) || !string.Equals(val2.Definition.Key, "LastSelectedModGuid", StringComparison.OrdinalIgnoreCase)) && (!flag || EntryMatchesSearch(val2, discoveredSection.Name, text)))
					{
						list.Add(val2);
					}
				}
				if (flag && list.Count == 0)
				{
					continue;
				}
				TMP_Text val3 = NativeWidgetFactory.CreateSectionHeader(_content, _labelTemplate, discoveredSection.Name);
				if ((Object)(object)val3 != (Object)null)
				{
					_dynamicRows.Add(((Component)val3).gameObject);
				}
				for (int k = 0; k < list.Count; k++)
				{
					ConfigEntryBase val4 = list[k];
					try
					{
						CreateEntryWidget(val4);
						num++;
						if (IsOwnPluginGeneralSection(discoveredPlugin, discoveredSection) && string.Equals(val4.Definition.Key, "RememberLastMod", StringComparison.OrdinalIgnoreCase))
						{
							CreateRememberedModPicker();
						}
					}
					catch (Exception ex)
					{
						ModdedWolfsConfigsPlugin.Log.LogWarning((object)$"Failed to create widget for {discoveredPlugin.Guid}/{val4.Definition}: {ex.Message}");
					}
				}
			}
			if (flag && num == 0)
			{
				TMP_Text val5 = NativeWidgetFactory.CreateSectionHeader(_content, _labelTemplate, "No settings match your search.");
				if ((Object)(object)val5 != (Object)null)
				{
					_dynamicRows.Add(((Component)val5).gameObject);
				}
			}
			WireNavigation();
		}

		private static bool EntryMatchesSearch(ConfigEntryBase entry, string sectionName, string query)
		{
			if (string.IsNullOrEmpty(query))
			{
				return true;
			}
			if (ContainsIgnoreCase(sectionName, query))
			{
				return true;
			}
			if (((entry != null) ? entry.Definition : null) != (ConfigDefinition)null && ContainsIgnoreCase(entry.Definition.Key, query))
			{
				return true;
			}
			if (ContainsIgnoreCase(ConfigDiscovery.GetDisplayName(entry), query))
			{
				return true;
			}
			return ContainsIgnoreCase(ResolveEntryDescription(entry), query);
		}

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

		private static bool IsOwnPluginGeneralSection(DiscoveredPlugin plugin, DiscoveredSection section)
		{
			if (plugin != null && string.Equals(plugin.Guid, "ModdedWolf.ModConfigs", StringComparison.OrdinalIgnoreCase))
			{
				return string.Equals(section.Name, "General", StringComparison.OrdinalIgnoreCase);
			}
			return false;
		}

		private void CreateRememberedModPicker()
		{
			List<string> list = BuildModOptionNames();
			int num = IndexForSavedModGuid();
			if (num < 0)
			{
				num = Mathf.Clamp(_selectedModIndex, 0, Mathf.Max(0, list.Count - 1));
			}
			Transform val = NativeWidgetFactory.CreateSettingBlock(_content, "LastSelectedMod");
			_dynamicRows.Add(((Component)val).gameObject);
			ModPicker modPicker = ModPicker.Create(val, _buttonTemplate, _labelTemplate, "Last selected mod", list, num, delegate(int index)
			{
				PersistRememberedModGuid(index);
				ConfigEntry<bool> rememberLastMod = ModdedWolfsConfigsPlugin.RememberLastMod;
				if (rememberLastMod != null && rememberLastMod.Value && index >= 0 && index < _plugins.Count)
				{
					_selectedModIndex = index;
					RefreshModDropdownOptions();
				}
			}, _inputFieldTemplate, _dropdownTemplate, useParentAsRow: false, enableSearch: true, "Search mods...", "(No mod configs found)");
			if ((Object)(object)modPicker?.Selectable != (Object)null)
			{
				_selectables.Add(modPicker.Selectable);
			}
			NativeWidgetFactory.CreateDescription(val, _labelTemplate, "Mod opened by default when you return to Mod Configs.");
		}

		private void CreateEntryWidget(ConfigEntryBase entry)
		{
			if (!ConfigDiscovery.ShouldRenderEntry(entry))
			{
				return;
			}
			if (string.Equals(entry.Definition.Key, "LastSelectedModGuid", StringComparison.OrdinalIgnoreCase))
			{
				ModdedWolfsConfigsPlugin.Log.LogWarning((object)"LastSelectedModGuid reached widget creation; skipping raw GUID field.");
				return;
			}
			string displayName = ConfigDiscovery.GetDisplayName(entry);
			Type settingType = entry.SettingType;
			string description = ResolveEntryDescription(entry);
			Transform val = NativeWidgetFactory.CreateSettingBlock(_content, displayName);
			_dynamicRows.Add(((Component)val).gameObject);
			if (ClientLocalBindings.IsBinding(entry))
			{
				CreateKeybindControl(entry, displayName, val);
				NativeWidgetFactory.CreateDescription(val, _labelTemplate, description);
				return;
			}
			if (TryGetBoolLike(entry, out var value, out var setBool) && (Object)(object)_toggleTemplate != (Object)null)
			{
				Toggle val2 = NativeWidgetFactory.CreateToggle(val, _toggleTemplate, _labelTemplate, displayName, delegate(bool obj)
				{
					setBool(obj);
					Save(entry);
				});
				val2.SetIsOnWithoutNotify(value);
				Track((Selectable)(object)val2);
				NativeWidgetFactory.CreateDescription(val, _labelTemplate, description);
				return;
			}
			if (IsNumericSettingType(settingType, out var wholeNumbers))
			{
				CreateNumericControl(entry, displayName, wholeNumbers, val);
				NativeWidgetFactory.CreateDescription(val, _labelTemplate, description);
				return;
			}
			if (settingType.IsEnum)
			{
				Array values = Enum.GetValues(settingType);
				List<string> list = new List<string>();
				int currentIndex = 0;
				object boxedValue = entry.BoxedValue;
				for (int num = 0; num < values.Length; num++)
				{
					list.Add(values.GetValue(num).ToString());
					if (object.Equals(values.GetValue(num), boxedValue))
					{
						currentIndex = num;
					}
				}
				CreateOptionPicker(val, displayName, list, currentIndex, delegate(int index)
				{
					if (index >= 0 && index < values.Length)
					{
						entry.BoxedValue = values.GetValue(index);
						Save(entry);
					}
				});
				NativeWidgetFactory.CreateDescription(val, _labelTemplate, description);
				return;
			}
			if (settingType == typeof(string))
			{
				ConfigDescription description2 = entry.Description;
				if (((description2 != null) ? description2.AcceptableValues : null) is AcceptableValueList<string> val3)
				{
					List<string> options = new List<string>(val3.AcceptableValues);
					int currentIndex2 = Mathf.Max(0, options.IndexOf((entry.BoxedValue as string) ?? string.Empty));
					CreateOptionPicker(val, displayName, options, currentIndex2, delegate(int index)
					{
						if (index >= 0 && index < options.Count)
						{
							entry.BoxedValue = options[index];
							Save(entry);
						}
					});
					NativeWidgetFactory.CreateDescription(val, _labelTemplate, description);
					return;
				}
			}
			CreateEditableTextEntry(entry, displayName, val);
			NativeWidgetFactory.CreateDescription(val, _labelTemplate, description);
		}

		private static string ResolveEntryDescription(ConfigEntryBase entry)
		{
			object obj;
			if (entry == null)
			{
				obj = null;
			}
			else
			{
				ConfigDescription description = entry.Description;
				obj = ((description != null) ? description.Description : null);
			}
			string text = (string)obj;
			if (!string.IsNullOrWhiteSpace(text))
			{
				return text;
			}
			object obj2;
			if (entry == null)
			{
				obj2 = null;
			}
			else
			{
				ConfigDescription description2 = entry.Description;
				obj2 = ((description2 != null) ? description2.Tags : null);
			}
			object[] array = (object[])obj2;
			if (array == null)
			{
				return null;
			}
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] is ConfigurationManagerAttributes configurationManagerAttributes && !string.IsNullOrWhiteSpace(configurationManagerAttributes.Description))
				{
					return configurationManagerAttributes.Description;
				}
			}
			return null;
		}

		private void CreateOptionPicker(Transform block, string label, List<string> options, int currentIndex, Action<int> onPicked)
		{
			ModPicker modPicker = ModPicker.Create(block, _buttonTemplate, _labelTemplate, label, options, currentIndex, onPicked, _inputFieldTemplate, _dropdownTemplate, useParentAsRow: false, ModPicker.ShouldEnableOptionSearch(options));
			if ((Object)(object)modPicker?.Selectable != (Object)null)
			{
				Track(modPicker.Selectable);
			}
		}

		private void CreateEditableTextEntry(ConfigEntryBase entry, string label, Transform parent)
		{
			ConfigEntryBase obj = entry;
			object a;
			if (obj == null)
			{
				a = null;
			}
			else
			{
				ConfigDefinition definition = obj.Definition;
				a = ((definition != null) ? definition.Key : null);
			}
			if (!string.Equals((string?)a, "LastSelectedModGuid", StringComparison.OrdinalIgnoreCase))
			{
				string initial = entry.GetSerializedValue() ?? entry.BoxedValue?.ToString() ?? string.Empty;
				Transform row = NativeWidgetFactory.CreateRow(parent, label);
				NativeWidgetFactory.CreateLabel(row, _labelTemplate, label);
				GuiInputField val = NativeWidgetFactory.CreateTextField(row, _inputFieldTemplate, initial, delegate(string text)
				{
					ApplyTextEntryValue(entry, text);
				});
				if ((Object)(object)val != (Object)null)
				{
					_selectables.Add((Selectable)(object)val);
				}
			}
		}

		private static void ApplyTextEntryValue(ConfigEntryBase entry, string text)
		{
			if (entry == null)
			{
				return;
			}
			if (text == null)
			{
				text = string.Empty;
			}
			try
			{
				if (entry.SettingType == typeof(string))
				{
					entry.BoxedValue = text;
				}
				else
				{
					entry.SetSerializedValue(text);
				}
				Save(entry);
			}
			catch (Exception ex)
			{
				ModdedWolfsConfigsPlugin.Log.LogWarning((object)$"Failed to apply text value for {entry.Definition}: {ex.Message}");
			}
		}

		private void CreateKeybindControl(ConfigEntryBase entry, string label, Transform parent)
		{
			string initial = entry.GetSerializedValue() ?? entry.BoxedValue?.ToString() ?? "None";
			Transform val = NativeWidgetFactory.CreateRow(parent, label);
			NativeWidgetFactory.CreateLabel(val, _labelTemplate, label);
			TMP_Text val2 = NativeWidgetFactory.CreateValueText(val, _labelTemplate, initial);
			if ((Object)(object)val2 != (Object)null)
			{
				val2.alignment = (TextAlignmentOptions)4097;
				LayoutElement component = ((Component)val2).GetComponent<LayoutElement>();
				if ((Object)(object)component != (Object)null)
				{
					component.minWidth = 140f;
					component.preferredWidth = 200f;
					component.flexibleWidth = 1f;
				}
			}
			Button val3 = NativeWidgetFactory.CreateInlineButton(val, _buttonTemplate, "Rebind", 140f);
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = NativeWidgetFactory.CreateStepButton(val, _buttonTemplate, "Rebind");
			}
			((Component)val).gameObject.AddComponent<KeybindCapture>().Bind(entry, val3, val2);
			if ((Object)(object)val3 != (Object)null)
			{
				_selectables.Add((Selectable)(object)val3);
			}
		}

		private void CreateNumericControl(ConfigEntryBase entry, string label, bool wholeNumbers, Transform parent)
		{
			GetNumericRange(entry, wholeNumbers, out var min, out var max, out var value, out var _);
			Type underlying = Nullable.GetUnderlyingType(entry.SettingType) ?? entry.SettingType;
			UnityAction<float> val = delegate(float v)
			{
				entry.BoxedValue = BoxNumeric(underlying, v);
				Save(entry);
			};
			if ((Object)(object)_sliderTemplate != (Object)null)
			{
				try
				{
					TMP_Text valueText;
					GuiInputField valueInput;
					Transform row;
					Slider val2 = NativeWidgetFactory.CreateSlider(parent, _sliderTemplate, _labelTemplate, _inputFieldTemplate, label, min, max, wholeNumbers, val, out valueText, out valueInput, out row);
					if ((Object)(object)val2 != (Object)null && (Object)(object)row != (Object)null)
					{
						val2.SetValueWithoutNotify(value);
						string text = FormatNumber(value, wholeNumbers);
						if ((Object)(object)valueInput != (Object)null)
						{
							NativeWidgetFactory.SetInputFieldText(valueInput, text);
							WireSliderValueInput(val2, valueInput, min, max, wholeNumbers, val);
							_selectables.Add((Selectable)(object)val2);
							_selectables.Add((Selectable)(object)valueInput);
							return;
						}
						if ((Object)(object)valueText != (Object)null)
						{
							valueText.text = text;
							((UnityEvent<float>)(object)val2.onValueChanged).AddListener((UnityAction<float>)delegate(float v)
							{
								valueText.text = FormatNumber(v, wholeNumbers);
							});
						}
						_selectables.Add((Selectable)(object)val2);
						return;
					}
				}
				catch (Exception ex)
				{
					ModdedWolfsConfigsPlugin.Log.LogWarning((object)$"Slider failed for {entry.Definition}, using stepper: {ex.Message}");
				}
			}
			NativeWidgetFactory.CreateNumericStepper(parent, _buttonTemplate, _labelTemplate, label, value, min, max, wholeNumbers, val, out var minusButton, out var plusButton, out var _, out var _);
			if ((Object)(object)minusButton != (Object)null)
			{
				_selectables.Add((Selectable)(object)minusButton);
			}
			if ((Object)(object)plusButton != (Object)null)
			{
				_selectables.Add((Selectable)(object)plusButton);
			}
		}

		private void WireSliderValueInput(Slider slider, GuiInputField valueInput, float min, float max, bool wholeNumbers, UnityAction<float> apply)
		{
			if ((Object)(object)slider == (Object)null || (Object)(object)valueInput == (Object)null)
			{
				return;
			}
			((UnityEvent<float>)(object)slider.onValueChanged).AddListener((UnityAction<float>)delegate(float v)
			{
				NativeWidgetFactory.SetInputFieldText(valueInput, FormatNumber(v, wholeNumbers));
			});
			((UnityEvent<string>)(object)((TMP_InputField)valueInput).onEndEdit).AddListener((UnityAction<string>)delegate(string text)
			{
				if (!TryParseSliderInput(text, wholeNumbers, out var value))
				{
					NativeWidgetFactory.SetInputFieldText(valueInput, FormatNumber(slider.value, wholeNumbers));
				}
				else
				{
					float num = Mathf.Clamp(value, min, max);
					if (wholeNumbers)
					{
						num = Mathf.Round(num);
					}
					slider.SetValueWithoutNotify(num);
					apply?.Invoke(num);
					NativeWidgetFactory.SetInputFieldText(valueInput, FormatNumber(num, wholeNumbers));
				}
			});
		}

		private static bool TryParseSliderInput(string text, bool wholeNumbers, out float value)
		{
			value = 0f;
			if (string.IsNullOrWhiteSpace(text))
			{
				return false;
			}
			text = text.Trim();
			if (wholeNumbers)
			{
				if (int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || int.TryParse(text, NumberStyles.Integer, CultureInfo.CurrentCulture, out result))
				{
					value = result;
					return true;
				}
				return false;
			}
			if (!float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out value))
			{
				return float.TryParse(text, NumberStyles.Float, CultureInfo.CurrentCulture, out value);
			}
			return true;
		}

		private static bool IsNumericSettingType(Type type, out bool wholeNumbers)
		{
			wholeNumbers = false;
			if (type == null)
			{
				return false;
			}
			type = Nullable.GetUnderlyingType(type) ?? type;
			if (type == typeof(int) || type == typeof(long) || type == typeof(short) || type == typeof(byte) || type == typeof(uint) || type == typeof(ushort) || type == typeof(sbyte))
			{
				wholeNumbers = true;
				return true;
			}
			if (type == typeof(float) || type == typeof(double) || type == typeof(decimal))
			{
				wholeNumbers = false;
				return true;
			}
			return false;
		}

		private static object BoxNumeric(Type type, float value)
		{
			if (type == typeof(int))
			{
				return Mathf.RoundToInt(value);
			}
			if (type == typeof(long))
			{
				return (long)Mathf.Round(value);
			}
			if (type == typeof(short))
			{
				return (short)Mathf.RoundToInt(value);
			}
			if (type == typeof(byte))
			{
				return (byte)Mathf.Clamp(Mathf.RoundToInt(value), 0, 255);
			}
			if (type == typeof(uint))
			{
				ret