Decompiled source of TrashDayModSettings v0.1.1

plugins/ModSettings.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Ox1;
using Trash;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.UIElements;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ModSettings")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.1.0")]
[assembly: AssemblyInformationalVersion("0.1.1+a507aeb1f3310ba08f9aabd708fe2f1dc170f347")]
[assembly: AssemblyProduct("ModSettings")]
[assembly: AssemblyTitle("ModSettings")]
[assembly: AssemblyVersion("0.1.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ModSettings
{
	internal sealed class ConfigurationManagerAttributes
	{
		public string DispName;

		public int? Order;
	}
	internal static class ConfigWriter
	{
		private static readonly HashSet<ConfigFile> Dirty = new HashSet<ConfigFile>();

		private static readonly HashSet<string> LoggedSaveFailures = new HashSet<string>();

		private static readonly SaveSchedule Schedule = new SaveSchedule();

		public static bool Set(ConfigEntryBase entry, object value)
		{
			ConfigFile configFile = entry.ConfigFile;
			bool saveOnConfigSet = configFile.SaveOnConfigSet;
			try
			{
				configFile.SaveOnConfigSet = false;
				entry.BoxedValue = value;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Couldn't set {entry.Definition} to '{value}': {arg}");
				return false;
			}
			finally
			{
				configFile.SaveOnConfigSet = saveOnConfigSet;
			}
			if (saveOnConfigSet)
			{
				Dirty.Add(configFile);
				Schedule.MarkDirty(Time.unscaledTime);
			}
			return true;
		}

		public static void Tick(float now)
		{
			if (Schedule.ShouldSave(now))
			{
				Save(now);
			}
		}

		public static void Flush()
		{
			Save(Time.unscaledTime);
		}

		private static void Save(float now)
		{
			Schedule.Saved();
			List<ConfigFile> list = new List<ConfigFile>();
			foreach (ConfigFile item in Dirty)
			{
				try
				{
					item.Save();
					LoggedSaveFailures.Remove(item.ConfigFilePath);
				}
				catch (Exception arg)
				{
					list.Add(item);
					if (LoggedSaveFailures.Add(item.ConfigFilePath))
					{
						Plugin.Log.LogError((object)$"Couldn't save {item.ConfigFilePath}; retrying. {arg}");
					}
				}
			}
			Dirty.Clear();
			foreach (ConfigFile item2 in list)
			{
				Dirty.Add(item2);
				Schedule.MarkDirty(now);
			}
		}
	}
	internal enum EditorKind
	{
		Toggle,
		Cycle,
		Dropdown,
		SliderInt,
		Slider,
		NumberText,
		Text,
		Key,
		ReadOnly
	}
	internal enum Acceptable
	{
		None,
		List,
		Range
	}
	internal static class EditorKinds
	{
		public const int MaxCycleChoices = 6;

		private static readonly Type[] Integers = new Type[8]
		{
			typeof(int),
			typeof(long),
			typeof(short),
			typeof(byte),
			typeof(sbyte),
			typeof(uint),
			typeof(ushort),
			typeof(ulong)
		};

		private static readonly Type[] Reals = new Type[3]
		{
			typeof(float),
			typeof(double),
			typeof(decimal)
		};

		public static bool IsInteger(Type type)
		{
			return Array.IndexOf(Integers, type) >= 0;
		}

		public static bool IsReal(Type type)
		{
			return Array.IndexOf(Reals, type) >= 0;
		}

		public static EditorKind Choose(Type type, bool isShortcut, Acceptable acceptable, int listCount)
		{
			if (type == typeof(bool))
			{
				return EditorKind.Toggle;
			}
			if (isShortcut)
			{
				return EditorKind.Key;
			}
			if (acceptable == Acceptable.List)
			{
				if (listCount <= 6)
				{
					return EditorKind.Cycle;
				}
				return EditorKind.Dropdown;
			}
			if (type.IsEnum)
			{
				if (type.IsDefined(typeof(FlagsAttribute), inherit: false))
				{
					return EditorKind.ReadOnly;
				}
				if (Enum.GetValues(type).Length <= 6)
				{
					return EditorKind.Cycle;
				}
				return EditorKind.Dropdown;
			}
			if (acceptable == Acceptable.Range)
			{
				if (IsInteger(type))
				{
					return EditorKind.SliderInt;
				}
				if (IsReal(type))
				{
					return EditorKind.Slider;
				}
			}
			if (IsInteger(type) || IsReal(type))
			{
				return EditorKind.NumberText;
			}
			if (type == typeof(string))
			{
				return EditorKind.Text;
			}
			return EditorKind.ReadOnly;
		}
	}
	internal static class Hotkey
	{
		public static bool WasPressed(KeyboardShortcut shortcut)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			Keyboard current = Keyboard.current;
			if (current == null || (int)((KeyboardShortcut)(ref shortcut)).MainKey == 0)
			{
				return false;
			}
			if (!TryGetKey(((KeyboardShortcut)(ref shortcut)).MainKey, out var key) || !((ButtonControl)current[key]).wasPressedThisFrame)
			{
				return false;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
			{
				if (!TryGetKey(modifier, out var key2) || !((ButtonControl)current[key2]).isPressed)
				{
					return false;
				}
			}
			return true;
		}

		public unsafe static bool TryGetKey(KeyCode code, out Key key)
		{
			if (Enum.TryParse<Key>(KeyNames.ToKeyName(((object)(*(KeyCode*)(&code))/*cast due to .constrained prefix*/).ToString()), ignoreCase: true, out key))
			{
				return (int)key != 0;
			}
			return false;
		}

		public unsafe static bool TryGetKeyCode(Key key, out KeyCode code)
		{
			if (Enum.TryParse<KeyCode>(KeyNames.ToKeyCodeName(((object)(*(Key*)(&key))/*cast due to .constrained prefix*/).ToString()), ignoreCase: true, out code))
			{
				return (int)code != 0;
			}
			return false;
		}
	}
	internal sealed class HotkeyController : MonoBehaviour
	{
		private static readonly FieldInfo OpenStacks = typeof(MenuSceneManager).GetField("_stack", BindingFlags.Static | BindingFlags.NonPublic);

		private static MenuScene _focusSwapped;

		private static string _originalFocusName;

		private bool _loggedError;

		private void Update()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				KeyRebind.Tick();
				ConfigWriter.Tick(Time.unscaledTime);
				if (Hotkey.WasPressed(Plugin.OpenKey.Value))
				{
					OnOpenKey();
				}
			}
			catch (Exception arg)
			{
				if (!_loggedError)
				{
					_loggedError = true;
					Plugin.Log.LogError((object)$"Mod settings update failed. {arg}");
				}
			}
		}

		private void OnDestroy()
		{
			ConfigWriter.Flush();
			RestoreFocusName();
		}

		private static void OnOpenKey()
		{
			FindHost(out var stack, out var hostScene, out var optionsScene);
			OptionsUI active = ModsTabInstaller.Active;
			switch (HotkeyGate.Decide(new HotkeyState
			{
				OptionsActive = ((Object)(object)active != (Object)null && ((Behaviour)active).isActiveAndEnabled),
				TextFieldFocused = TextFieldFocused(active),
				Rebinding = KeyRebind.Listening,
				Loading = LoadingScreenUI.IsVisible,
				MenusSuppressed = MenuSceneManager.MenusSuppressed,
				HasMenuHost = ((Object)(object)stack != (Object)null && (Object)(object)optionsScene != (Object)null),
				OtherMenuOpen = OtherMenuOpen(stack, hostScene, optionsScene)
			}))
			{
			case HotkeyAction.ShowModsTab:
				ModsTabInstaller.ShowMods(active);
				break;
			case HotkeyAction.OpenOptions:
				Open(stack, optionsScene);
				break;
			}
		}

		private static void FindHost(out MenuSceneStack stack, out MenuScene hostScene, out MenuScene optionsScene)
		{
			stack = null;
			hostScene = null;
			optionsScene = null;
			MidgameUI val = Object.FindFirstObjectByType<MidgameUI>((FindObjectsInactive)1);
			if ((Object)(object)val != (Object)null)
			{
				optionsScene = val.OptionsScene;
				hostScene = ((Component)val).GetComponentInParent<MenuScene>(true);
				stack = ((Component)val).GetComponentInParent<MenuSceneStack>(true);
				return;
			}
			MainMenuUI val2 = Object.FindFirstObjectByType<MainMenuUI>((FindObjectsInactive)1);
			if ((Object)(object)val2 != (Object)null)
			{
				optionsScene = val2.OptionsScene;
				hostScene = ((Component)val2).GetComponentInParent<MenuScene>(true);
				stack = ((Component)val2).GetComponentInParent<MenuSceneStack>(true);
			}
		}

		private static bool OtherMenuOpen(MenuSceneStack stack, MenuScene hostScene, MenuScene optionsScene)
		{
			if (OpenStacks?.GetValue(null) is List<MenuSceneStack> list)
			{
				foreach (MenuSceneStack item in list)
				{
					if ((Object)(object)item != (Object)(object)stack)
					{
						return true;
					}
				}
			}
			MenuScene val = default(MenuScene);
			if ((Object)(object)stack != (Object)null && MenuSceneManager.IsStackOpen(stack) && stack.TryGetActiveScene(ref val))
			{
				if ((Object)(object)val != (Object)(object)hostScene)
				{
					return (Object)(object)val != (Object)(object)optionsScene;
				}
				return false;
			}
			return false;
		}

		private static bool TextFieldFocused(OptionsUI options)
		{
			if ((Object)(object)options == (Object)null)
			{
				return false;
			}
			object obj;
			if (!OptionsAccess.Ready)
			{
				obj = null;
			}
			else
			{
				VisualElement obj2 = OptionsAccess.Root(options);
				object obj3;
				if (obj2 == null)
				{
					obj3 = null;
				}
				else
				{
					IPanel panel = obj2.panel;
					if (panel == null)
					{
						obj3 = null;
					}
					else
					{
						FocusController focusController = panel.focusController;
						obj3 = ((focusController != null) ? focusController.focusedElement : null);
					}
				}
				obj = ((obj3 is VisualElement) ? obj3 : null);
			}
			VisualElement val = (VisualElement)obj;
			if (!(val is TextField))
			{
				return ((val != null) ? val.GetFirstAncestorOfType<TextField>() : null) != null;
			}
			return true;
		}

		private static void Open(MenuSceneStack stack, MenuScene optionsScene)
		{
			RestoreFocusName();
			_focusSwapped = optionsScene;
			_originalFocusName = optionsScene.DefaultFocusElementName;
			optionsScene.DefaultFocusElementName = "ModsTabBtn";
			ModsTabInstaller.OpenOnModsPending = true;
			try
			{
				stack.PushActiveScene(optionsScene);
			}
			finally
			{
				ModsTabInstaller.OpenOnModsPending = false;
			}
		}

		internal static void RestoreFocusName()
		{
			if (!((Object)(object)_focusSwapped == (Object)null))
			{
				_focusSwapped.DefaultFocusElementName = _originalFocusName;
				_focusSwapped = null;
				_originalFocusName = null;
			}
		}
	}
	internal enum HotkeyAction
	{
		None,
		ShowModsTab,
		OpenOptions
	}
	internal struct HotkeyState
	{
		public bool OptionsActive;

		public bool TextFieldFocused;

		public bool Rebinding;

		public bool Loading;

		public bool MenusSuppressed;

		public bool HasMenuHost;

		public bool OtherMenuOpen;
	}
	internal static class HotkeyGate
	{
		public static HotkeyAction Decide(HotkeyState s)
		{
			if (s.TextFieldFocused || s.Rebinding || s.Loading || s.MenusSuppressed || s.OtherMenuOpen)
			{
				return HotkeyAction.None;
			}
			if (s.OptionsActive)
			{
				return HotkeyAction.ShowModsTab;
			}
			if (!s.HasMenuHost)
			{
				return HotkeyAction.None;
			}
			return HotkeyAction.OpenOptions;
		}
	}
	internal static class KeyNames
	{
		private static readonly (string KeyCode, string Key)[] Renamed = new(string, string)[16]
		{
			("Return", "Enter"),
			("KeypadEnter", "NumpadEnter"),
			("KeypadPlus", "NumpadPlus"),
			("KeypadMinus", "NumpadMinus"),
			("KeypadMultiply", "NumpadMultiply"),
			("KeypadDivide", "NumpadDivide"),
			("KeypadPeriod", "NumpadPeriod"),
			("KeypadEquals", "NumpadEquals"),
			("LeftControl", "LeftCtrl"),
			("RightControl", "RightCtrl"),
			("LeftCommand", "LeftMeta"),
			("RightCommand", "RightMeta"),
			("BackQuote", "Backquote"),
			("Print", "PrintScreen"),
			("Numlock", "NumLock"),
			("Menu", "ContextMenu")
		};

		private static readonly string[] Modifiers = new string[9] { "LeftControl", "RightControl", "LeftShift", "RightShift", "LeftAlt", "RightAlt", "LeftCommand", "RightCommand", "AltGr" };

		public static string ToKeyName(string keyCode)
		{
			(string, string)[] renamed = Renamed;
			for (int i = 0; i < renamed.Length; i++)
			{
				var (text, result) = renamed[i];
				if (text == keyCode)
				{
					return result;
				}
			}
			if (keyCode.StartsWith("Alpha", StringComparison.Ordinal))
			{
				return "Digit" + keyCode.Substring("Alpha".Length);
			}
			if (keyCode.StartsWith("Keypad", StringComparison.Ordinal))
			{
				return "Numpad" + keyCode.Substring("Keypad".Length);
			}
			return keyCode;
		}

		public static string ToKeyCodeName(string key)
		{
			(string, string)[] renamed = Renamed;
			for (int i = 0; i < renamed.Length; i++)
			{
				(string, string) tuple = renamed[i];
				var (result, _) = tuple;
				if (tuple.Item2 == key)
				{
					return result;
				}
			}
			if (key.StartsWith("Digit", StringComparison.Ordinal))
			{
				return "Alpha" + key.Substring("Digit".Length);
			}
			if (key.StartsWith("Numpad", StringComparison.Ordinal))
			{
				return "Keypad" + key.Substring("Numpad".Length);
			}
			return key;
		}

		public static bool IsModifier(string keyCode)
		{
			return Array.IndexOf(Modifiers, keyCode) >= 0;
		}
	}
	internal static class KeyRebind
	{
		private static Button _listening;

		private static Func<object, bool> _set;

		private static Action _restore;

		private static int _startFrame;

		private static int _cancelledFrame = -10;

		public static bool Listening => _listening != null;

		public static bool ConsumesCancel
		{
			get
			{
				if (_listening == null)
				{
					return Time.frameCount - _cancelledFrame <= 1;
				}
				return true;
			}
		}

		public unsafe static Button Create(SettingRow row, ConfigEntryBase entry, Func<object, bool> set, out Action refresh)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			VisualElement val = new VisualElement();
			val.AddToClassList("cycle-control");
			Button button = new Button();
			((VisualElement)button).AddToClassList("options-text");
			((VisualElement)button).AddToClassList("cycle-btn");
			((VisualElement)button).AddToClassList("cycle-btn-single");
			Action update = delegate
			{
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				if (_listening != button)
				{
					KeyboardShortcut val2 = (KeyboardShortcut)entry.BoxedValue;
					((TextElement)button).text = (((int)((KeyboardShortcut)(ref val2)).MainKey == 0) ? "Not bound" : ((object)(*(KeyboardShortcut*)(&val2))/*cast due to .constrained prefix*/).ToString());
				}
			};
			button.clicked += delegate
			{
				if (_listening != button)
				{
					Cancel();
					_listening = button;
					_set = set;
					_restore = update;
					_startFrame = Time.frameCount;
					((TextElement)button).text = "Press a key…";
				}
			};
			((CallbackEventHandler)button).RegisterCallback<DetachFromPanelEvent>((EventCallback<DetachFromPanelEvent>)delegate
			{
				if (_listening == button)
				{
					Cancel();
				}
			}, (TrickleDown)0);
			val.Add((VisualElement)(object)button);
			((VisualElement)row).Add(val);
			update();
			refresh = update;
			return button;
		}

		public static void Cancel()
		{
			if (_listening != null)
			{
				Action restore = _restore;
				End();
				restore?.Invoke();
			}
		}

		public unsafe static void Tick()
		{
			//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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Invalid comparison between Unknown and I4
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			if (_listening == null)
			{
				return;
			}
			if (((VisualElement)_listening).panel == null)
			{
				Cancel();
				return;
			}
			Keyboard current = Keyboard.current;
			if (current == null || Time.frameCount == _startFrame)
			{
				return;
			}
			if (((ButtonControl)current.escapeKey).wasPressedThisFrame)
			{
				Cancel();
				return;
			}
			Enumerator<KeyControl> enumerator = current.allKeys.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					KeyControl current2 = enumerator.Current;
					if (current2 != null && ((ButtonControl)current2).wasPressedThisFrame && Hotkey.TryGetKeyCode(current2.keyCode, out var code) && !KeyNames.IsModifier(((object)(*(KeyCode*)(&code))/*cast due to .constrained prefix*/).ToString()))
					{
						Func<object, bool> set = _set;
						Action restore = _restore;
						End();
						set((object)(KeyboardShortcut)(((int)code == 8) ? KeyboardShortcut.Empty : new KeyboardShortcut(code, HeldModifiers(current))));
						restore();
						break;
					}
				}
			}
			finally
			{
				((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
			}
		}

		private static void End()
		{
			_listening = null;
			_set = null;
			_restore = null;
			_cancelledFrame = Time.frameCount;
		}

		private static KeyCode[] HeldModifiers(Keyboard keyboard)
		{
			List<KeyCode> list = new List<KeyCode>();
			if (((ButtonControl)keyboard.leftCtrlKey).isPressed)
			{
				list.Add((KeyCode)306);
			}
			if (((ButtonControl)keyboard.rightCtrlKey).isPressed)
			{
				list.Add((KeyCode)305);
			}
			if (((ButtonControl)keyboard.leftShiftKey).isPressed)
			{
				list.Add((KeyCode)304);
			}
			if (((ButtonControl)keyboard.rightShiftKey).isPressed)
			{
				list.Add((KeyCode)303);
			}
			if (((ButtonControl)keyboard.leftAltKey).isPressed)
			{
				list.Add((KeyCode)308);
			}
			if (((ButtonControl)keyboard.rightAltKey).isPressed)
			{
				list.Add((KeyCode)307);
			}
			if (((ButtonControl)keyboard.leftMetaKey).isPressed)
			{
				list.Add((KeyCode)310);
			}
			if (((ButtonControl)keyboard.rightMetaKey).isPressed)
			{
				list.Add((KeyCode)309);
			}
			return list.ToArray();
		}
	}
	internal sealed class ModsTab
	{
		private static string _rememberedGuid;

		private static readonly HashSet<string> LoggedRows = new HashSet<string>();

		private readonly VisualElement _container;

		private readonly VisualElement _skinRoot;

		private readonly Action<VisualElement, VisualElement> _wireEdges;

		private readonly List<Action> _refreshers = new List<Action>();

		private List<ModInfo> _mods = new List<ModInfo>();

		private ModInfo _selected;

		private Button _picker;

		public ModsTab(VisualElement container, VisualElement skinRoot, Action<VisualElement, VisualElement> wireEdges)
		{
			_container = container;
			_skinRoot = skinRoot;
			_wireEdges = wireEdges;
		}

		public void Rebuild()
		{
			_mods = SettingsRegistry.Collect();
			Render();
		}

		public void ResetSelectedMod()
		{
			if (_selected == null)
			{
				return;
			}
			foreach (SettingInfo setting in _selected.Settings)
			{
				if (!setting.Hidden && !setting.ReadOnly)
				{
					ConfigWriter.Set(setting.Entry, setting.Entry.DefaultValue);
				}
			}
			RefreshAll();
		}

		private void Select(int index)
		{
			_rememberedGuid = _mods[Picker.Wrap(index, _mods.Count)].Guid;
			Render();
			Button picker = _picker;
			if (picker != null)
			{
				((Focusable)picker).Focus();
			}
		}

		private void Render()
		{
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			KeyRebind.Cancel();
			_container.Clear();
			_refreshers.Clear();
			_picker = null;
			_selected = null;
			if (_mods.Count == 0)
			{
				Rows.Message(_container, "No installed mods have settings.");
				_wireEdges(null, null);
				return;
			}
			int index = Picker.IndexOf(_mods.Select((ModInfo m) => m.Guid).ToList(), _rememberedGuid);
			_selected = _mods[index];
			_rememberedGuid = _selected.Guid;
			SettingRow val = Rows.Row("Mod", null);
			ModInfo mod = _selected;
			_picker = Rows.Cycle(val, () => mod.Name + "  " + mod.Version, delegate
			{
				Select(index + 1);
			}, delegate
			{
				Select(index - 1);
			}, out var _);
			_container.Add((VisualElement)(object)val);
			foreach (SettingGroup<SettingInfo> item in SettingOrder.Group(_selected.Settings, (SettingInfo s) => s.Facts))
			{
				Rows.Heading(_container, item.Heading);
				foreach (SettingInfo item2 in item.Items)
				{
					_refreshers.Add(BuildRow(item2));
				}
			}
			VisualElement val2 = UQueryExtensions.Query<VisualElement>(_container, (string)null, (string)null).Where((Func<VisualElement, bool>)((VisualElement v) => ((Focusable)v).focusable && ((Focusable)v).canGrabFocus)).ToList()
				.LastOrDefault();
			_wireEdges((VisualElement)(object)_picker, (VisualElement)(((object)val2) ?? ((object)_picker)));
		}

		private Action BuildRow(SettingInfo setting)
		{
			int childCount = _container.childCount;
			try
			{
				return SettingEditors.Build(_container, setting, _skinRoot, RefreshAll);
			}
			catch (Exception arg)
			{
				while (_container.childCount > childCount)
				{
					_container.RemoveAt(_container.childCount - 1);
				}
				SettingEditors.BuildBroken(_container, setting);
				if (LoggedRows.Add($"{setting.Mod.Guid}/{setting.Entry.Definition}"))
				{
					Plugin.Log.LogWarning((object)$"Can't show {setting.Mod.Name} / {setting.Entry.Definition} in the Mods tab. {arg}");
				}
				return delegate
				{
				};
			}
		}

		private void RefreshAll()
		{
			foreach (Action refresher in _refreshers)
			{
				refresher();
			}
		}
	}
	internal static class ModsTabInstaller
	{
		public const string ButtonName = "ModsTabBtn";

		public const string ContentName = "ModsTab";

		private static bool _warned;

		public static bool OpenOnModsPending;

		public static OptionsUI Active { get; private set; }

		public static void Install(OptionsUI ui)
		{
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			Active = ui;
			if (!OptionsAccess.Ready)
			{
				return;
			}
			VisualElement val = OptionsAccess.Root(ui);
			object obj;
			if (val == null)
			{
				obj = null;
			}
			else
			{
				VisualElement obj2 = UQueryExtensions.Q<VisualElement>(val, "OptionsPanel", (string)null);
				obj = ((obj2 != null) ? UQueryExtensions.Q<VisualElement>(obj2, (string)null, "content-area") : null);
			}
			if (obj == null)
			{
				obj = val;
			}
			VisualElement val2 = (VisualElement)obj;
			Button val3 = ((val != null) ? UQueryExtensions.Q<Button>(val, "KeybindsTabBtn", (string)null) : null);
			VisualElement val4 = ((val2 != null) ? UQueryExtensions.Q<VisualElement>(val2, "AudioTab", (string)null) : null);
			if (val == null || val3 == null || val4 == null)
			{
				if (!_warned)
				{
					_warned = true;
					Plugin.Log.LogWarning((object)"The Options screen layout changed (KeybindsTabBtn or AudioTab not found); the Mods tab is unavailable.");
				}
				return;
			}
			Button button = UQueryExtensions.Q<Button>(val, "ModsTabBtn", (string)null) ?? CreateButton(ui, val3);
			VisualElement content = UQueryExtensions.Q<VisualElement>(val2, "ModsTab", (string)null) ?? CreateContent(val4);
			if (((VisualElement)button).userData == null)
			{
				((VisualElement)button).userData = OptionsAccess.MakeTab(button, content, delegate
				{
					(content.userData as ModsTab)?.ResetSelectedMod();
				});
				WireButton(ui, button, content);
			}
			object userData = ((VisualElement)button).userData;
			OptionsAccess.AppendTab(ui, userData);
			content.style.display = StyleEnum<DisplayStyle>.op_Implicit((DisplayStyle)1);
			((VisualElement)button).RemoveFromClassList("tab-button--active");
			VisualElement parent = ((VisualElement)button).parent;
			if (parent != null)
			{
				parent.RemoveFromClassList("tab-button-container--active");
			}
			ModsTab modsTab = content.userData as ModsTab;
			if (modsTab == null)
			{
				modsTab = new ModsTab((VisualElement)(object)UQueryExtensions.Q<ScrollView>(content, (string)null, (string)null), val, delegate(VisualElement first, VisualElement last)
				{
					if (first != null)
					{
						OptionsAccess.SetNav(ui, first, (Direction)2, (VisualElement _) => (VisualElement)(object)button);
					}
					if (last != null)
					{
						OptionsAccess.SetNav(ui, last, (Direction)4, (VisualElement _) => (VisualElement)(object)OptionsAccess.ResetButton(ui));
					}
				});
				content.userData = modsTab;
			}
			modsTab.Rebuild();
			if (OpenOnModsPending)
			{
				OpenOnModsPending = false;
				OptionsAccess.ClickTab(ui, userData);
			}
		}

		public static void Closed(OptionsUI ui)
		{
			KeyRebind.Cancel();
			ConfigWriter.Flush();
			HotkeyController.RestoreFocusName();
			if ((Object)(object)Active == (Object)(object)ui)
			{
				Active = null;
			}
		}

		public static void ShowMods(OptionsUI ui)
		{
			VisualElement obj = OptionsAccess.Root(ui);
			object obj2;
			if (obj == null)
			{
				obj2 = null;
			}
			else
			{
				Button obj3 = UQueryExtensions.Q<Button>(obj, "ModsTabBtn", (string)null);
				obj2 = ((obj3 != null) ? ((VisualElement)obj3).userData : null);
			}
			object obj4 = obj2;
			if (obj4 != null)
			{
				OptionsAccess.ClickTab(ui, obj4);
			}
		}

		private static Button CreateButton(OptionsUI ui, Button template)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			Button val = new Button
			{
				name = "ModsTabBtn"
			};
			CopyClasses((VisualElement)(object)template, (VisualElement)(object)val, "tab-button--active");
			if (!string.IsNullOrEmpty(((TextElement)template).text))
			{
				((TextElement)val).text = "Mods";
			}
			else
			{
				Label val2 = UQueryExtensions.Q<Label>((VisualElement)(object)template, (string)null, (string)null);
				Label val3 = new Label("Mods");
				if (val2 != null)
				{
					CopyClasses((VisualElement)(object)val2, (VisualElement)(object)val3);
				}
				((VisualElement)val).Add((VisualElement)(object)val3);
			}
			VisualElement parent = ((VisualElement)template).parent;
			if (parent != null && parent.parent != null && UQueryExtensions.Query<Button>(parent, (string)null, (string)null).ToList().Count == 1)
			{
				VisualElement val4 = new VisualElement();
				CopyClasses(parent, val4, "tab-button-container--active", "tab-button-container--focused");
				val4.Add((VisualElement)(object)val);
				parent.parent.Insert(parent.parent.IndexOf(parent) + 1, val4);
			}
			else if (parent != null)
			{
				parent.Insert(parent.IndexOf((VisualElement)(object)template) + 1, (VisualElement)(object)val);
			}
			return val;
		}

		private static void WireButton(OptionsUI ui, Button button, VisualElement content)
		{
			button.clicked += delegate
			{
				OptionsAccess.ClickTab(ui, ((VisualElement)button).userData);
			};
			((CallbackEventHandler)button).RegisterCallback<FocusInEvent>((EventCallback<FocusInEvent>)delegate
			{
				OptionsAccess.TabButtonFocused(ui, ((VisualElement)button).userData);
				VisualElement parent = ((VisualElement)button).parent;
				if (parent != null)
				{
					parent.AddToClassList("tab-button-container--focused");
				}
			}, (TrickleDown)0);
			((CallbackEventHandler)button).RegisterCallback<FocusOutEvent>((EventCallback<FocusOutEvent>)delegate
			{
				VisualElement parent = ((VisualElement)button).parent;
				if (parent != null)
				{
					parent.RemoveFromClassList("tab-button-container--focused");
				}
			}, (TrickleDown)0);
			OptionsAccess.SetNav(ui, (VisualElement)(object)button, (Direction)2, (VisualElement _) => Focusables(content).LastOrDefault());
			OptionsAccess.SetNav(ui, (VisualElement)(object)button, (Direction)4, (VisualElement _) => Focusables(content).FirstOrDefault());
		}

		private static VisualElement CreateContent(VisualElement template)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_005c: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			VisualElement val = new VisualElement
			{
				name = "ModsTab"
			};
			CopyClasses(template, val);
			val.style.display = StyleEnum<DisplayStyle>.op_Implicit((DisplayStyle)1);
			ScrollView scroll = new ScrollView((ScrollViewMode)0);
			scroll.horizontalScrollerVisibility = (ScrollerVisibility)2;
			((VisualElement)scroll).style.flexGrow = StyleFloat.op_Implicit(1f);
			foreach (VisualElement item in UQueryExtensions.Query<VisualElement>((VisualElement)(object)scroll, (string)null, (string)null).ToList())
			{
				if ((object)item != scroll && item != ((VisualElement)scroll).contentContainer)
				{
					((Focusable)item).focusable = false;
				}
			}
			((CallbackEventHandler)scroll).RegisterCallback<FocusInEvent>((EventCallback<FocusInEvent>)delegate(FocusInEvent e)
			{
				IEventHandler target = ((EventBase)e).target;
				VisualElement val2 = (VisualElement)(object)((target is VisualElement) ? target : null);
				if (val2 != null && (object)val2 != scroll && ((VisualElement)scroll).contentContainer.Contains(val2))
				{
					scroll.ScrollTo(val2);
				}
			}, (TrickleDown)1);
			val.Add((VisualElement)(object)scroll);
			template.parent.Insert(template.parent.IndexOf(template) + 1, val);
			return val;
		}

		private static List<VisualElement> Focusables(VisualElement container)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			return UQueryExtensions.Query<VisualElement>(container, (string)null, (string)null).Where((Func<VisualElement, bool>)((VisualElement v) => ((Focusable)v).focusable && ((Focusable)v).canGrabFocus)).ToList();
		}

		private static void CopyClasses(VisualElement from, VisualElement to, params string[] except)
		{
			foreach (string @class in from.GetClasses())
			{
				if (!@class.StartsWith("unity-", StringComparison.Ordinal) && Array.IndexOf(except, @class) < 0)
				{
					to.AddToClassList(@class);
				}
			}
		}
	}
	internal static class Names
	{
		public static string Humanize(string key)
		{
			if (string.IsNullOrEmpty(key) || key.Contains(" "))
			{
				return key;
			}
			List<char> list = new List<char>(key.Length + 8);
			for (int i = 0; i < key.Length; i++)
			{
				char c = key[i];
				if (c == '_')
				{
					list.Add(' ');
					continue;
				}
				if (i > 0 && char.IsUpper(c) && key[i - 1] != '_' && (char.IsLower(key[i - 1]) || (i + 1 < key.Length && char.IsLower(key[i + 1]) && char.IsUpper(key[i - 1]))))
				{
					list.Add(' ');
				}
				list.Add(c);
			}
			return new string(list.ToArray());
		}
	}
	internal static class OptionsAccess
	{
		private static Type _tabType;

		private static FieldInfo _tabButton;

		private static FieldInfo _tabContent;

		private static FieldInfo _tabReset;

		private static FieldInfo _tabs;

		private static FieldInfo _root;

		private static FieldInfo _currentTab;

		private static FieldInfo _resetButton;

		private static MethodInfo _clickTab;

		private static MethodInfo _tabButtonFocused;

		private static MethodInfo _setNav;

		public static bool Ready { get; private set; }

		public static bool Init()
		{
			Type typeFromHandle = typeof(OptionsUI);
			_tabType = typeFromHandle.GetNestedType("Tab", BindingFlags.Public | BindingFlags.NonPublic);
			_tabButton = _tabType?.GetField("Button", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			_tabContent = _tabType?.GetField("Content", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			_tabReset = _tabType?.GetField("ResetDefaults", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			_tabs = typeFromHandle.GetField("_tabs", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			_root = typeFromHandle.GetField("_root", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			_currentTab = typeFromHandle.GetField("_currentTab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			_resetButton = typeFromHandle.GetField("_resetDefaultsBtn", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			_clickTab = ((_tabType == null) ? null : typeFromHandle.GetMethod("ClickTab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { _tabType }, null));
			_tabButtonFocused = ((_tabType == null) ? null : typeFromHandle.GetMethod("OnTabButtonFocused", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { _tabType }, null));
			_setNav = typeFromHandle.GetMethod("SetDirectionalNavForElement", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			List<string> missing = new List<string>();
			Check(_tabType, "Tab");
			Check(_tabButton, "Tab.Button");
			Check(_tabContent, "Tab.Content");
			Check(_tabReset, "Tab.ResetDefaults");
			Check(_tabs, "_tabs");
			Check(_root, "_root");
			Check(_currentTab, "_currentTab");
			Check(_resetButton, "_resetDefaultsBtn");
			Check(_clickTab, "ClickTab");
			Check(_tabButtonFocused, "OnTabButtonFocused");
			Check(_setNav, "SetDirectionalNavForElement");
			Ready = missing.Count == 0;
			if (!Ready)
			{
				Plugin.Log.LogWarning((object)("The Options screen changed (" + string.Join(", ", missing) + " not found); the Mods tab is unavailable."));
			}
			return Ready;
			void Check(object member, string name)
			{
				if (member == null)
				{
					missing.Add(name);
				}
			}
		}

		public static VisualElement Root(OptionsUI ui)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			return (VisualElement)_root.GetValue(ui);
		}

		public static Button ResetButton(OptionsUI ui)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			return (Button)_resetButton.GetValue(ui);
		}

		public static object MakeTab(Button button, VisualElement content, Action resetDefaults)
		{
			object obj = Activator.CreateInstance(_tabType);
			_tabButton.SetValue(obj, button);
			_tabContent.SetValue(obj, content);
			_tabReset.SetValue(obj, resetDefaults);
			return obj;
		}

		public static void AppendTab(OptionsUI ui, object tab)
		{
			Array array = (Array)_tabs.GetValue(ui);
			object value = _tabContent.GetValue(tab);
			foreach (object item in array)
			{
				if (_tabContent.GetValue(item) == value)
				{
					return;
				}
			}
			Array array2 = Array.CreateInstance(_tabType, array.Length + 1);
			Array.Copy(array, array2, array.Length);
			array2.SetValue(tab, array.Length);
			_tabs.SetValue(ui, array2);
		}

		public static bool IsCurrent(OptionsUI ui, VisualElement content)
		{
			return _tabContent.GetValue(_currentTab.GetValue(ui)) == content;
		}

		public static void ClickTab(OptionsUI ui, object tab)
		{
			_clickTab.Invoke(ui, new object[1] { tab });
		}

		public static void TabButtonFocused(OptionsUI ui, object tab)
		{
			_tabButtonFocused.Invoke(ui, new object[1] { tab });
		}

		public static void SetNav(OptionsUI ui, VisualElement element, Direction direction, Func<VisualElement, VisualElement> next)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			_setNav.Invoke(ui, new object[3] { element, direction, next });
		}
	}
	internal static class Picker
	{
		public static int Wrap(int index, int count)
		{
			if (count > 0)
			{
				return (index % count + count) % count;
			}
			return -1;
		}

		public static int IndexOf(IReadOnlyList<string> ids, string remembered)
		{
			if (ids.Count == 0)
			{
				return -1;
			}
			for (int i = 0; i < ids.Count; i++)
			{
				if (string.Equals(ids[i], remembered, StringComparison.Ordinal))
				{
					return i;
				}
			}
			return 0;
		}
	}
	[BepInPlugin("com.darkharasho.trashday.modsettings", "ModSettings", "0.1.1")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.darkharasho.trashday.modsettings";

		public const string PluginName = "ModSettings";

		public const string PluginVersion = "0.1.1";

		internal static ManualLogSource Log;

		internal static ConfigEntry<KeyboardShortcut> OpenKey;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0025: 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: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Expected O, but got Unknown
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			OpenKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "OpenKey", new KeyboardShortcut((KeyCode)291, Array.Empty<KeyCode>()), new ConfigDescription("Opens the game's Options screen on the Mods tab.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					DispName = "Open key"
				}
			}));
			_harmony = new Harmony("com.darkharasho.trashday.modsettings");
			try
			{
				_harmony.PatchAll();
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Patching failed, likely a game update; the Mods tab is unavailable. {arg}");
				_harmony.UnpatchSelf();
				return;
			}
			OptionsAccess.Init();
			GameObject val = new GameObject("ModSettings");
			Object.DontDestroyOnLoad((Object)val);
			((Object)val).hideFlags = (HideFlags)61;
			val.AddComponent<HotkeyController>();
			Log.LogInfo((object)string.Format("{0} {1} loaded; press {2} for the Mods tab", "ModSettings", "0.1.1", OpenKey.Value));
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal static class Rows
	{
		public static SettingRow Row(string label, string description)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0023: 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_0039: Expected O, but got Unknown
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_0085: 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)
			SettingRow val = new SettingRow();
			VisualElement val2 = new VisualElement();
			val2.AddToClassList("setting-label");
			val2.style.flexDirection = StyleEnum<FlexDirection>.op_Implicit((FlexDirection)0);
			Label name = new Label(label);
			((VisualElement)name).AddToClassList("options-text");
			val2.Add((VisualElement)(object)name);
			if (!string.IsNullOrEmpty(description))
			{
				Label note = new Label(description);
				((VisualElement)note).AddToClassList("options-text");
				((VisualElement)note).style.whiteSpace = StyleEnum<WhiteSpace>.op_Implicit((WhiteSpace)0);
				((VisualElement)note).style.opacity = StyleFloat.op_Implicit(0.7f);
				((CallbackEventHandler)name).RegisterCallback<GeometryChangedEvent>((EventCallback<GeometryChangedEvent>)delegate
				{
					//IL_0049: Unknown result type (might be due to invalid IL or missing references)
					float num = ((VisualElement)name).resolvedStyle.fontSize * 0.6f;
					if (num > 0f && Math.Abs(((VisualElement)note).resolvedStyle.fontSize - num) > 0.5f)
					{
						((VisualElement)note).style.fontSize = StyleLength.op_Implicit(num);
					}
				}, (TrickleDown)0);
				val2.Add((VisualElement)(object)note);
			}
			((VisualElement)val).Add(val2);
			return val;
		}

		public static Button Cycle(SettingRow row, Func<string> text, Action next, Action previous, out Action refresh)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			VisualElement val = new VisualElement();
			val.AddToClassList("cycle-control");
			Button button = new Button();
			((VisualElement)button).AddToClassList("options-text");
			((VisualElement)button).AddToClassList("cycle-btn");
			((VisualElement)button).AddToClassList("cycle-btn-single");
			Action update = delegate
			{
				((TextElement)button).text = text();
			};
			button.clicked += delegate
			{
				next();
				update();
			};
			((CallbackEventHandler)button).RegisterCallback<NavigationMoveEvent>((EventCallback<NavigationMoveEvent>)delegate(NavigationMoveEvent evt)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Invalid comparison between Unknown and I4
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Invalid comparison between Unknown and I4
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Invalid comparison between Unknown and I4
				if ((int)evt.direction == 1 || (int)evt.direction == 3)
				{
					IPanel panel = ((VisualElement)button).panel;
					FocusController obj = ((panel != null) ? panel.focusController : null);
					if ((int)evt.direction == 1)
					{
						previous();
					}
					else
					{
						next();
					}
					update();
					((EventBase)evt).StopPropagation();
					if (obj != null)
					{
						obj.IgnoreEvent((EventBase)(object)evt);
					}
				}
			}, (TrickleDown)0);
			val.Add((VisualElement)(object)button);
			((VisualElement)row).Add(val);
			update();
			refresh = update;
			return button;
		}

		public static Slider Slider(SettingRow row, float low, float high, bool integer, Func<float> get, Action<float> set, out Action refresh)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			VisualElement val = new VisualElement();
			val.AddToClassList("setting-control");
			Label valueLabel = new Label();
			((VisualElement)valueLabel).AddToClassList("options-text");
			((VisualElement)valueLabel).AddToClassList("slider-value-label");
			Slider slider = new Slider(low, high, (SliderDirection)0, 0f);
			((VisualElement)slider).AddToClassList("setting-slider");
			INotifyValueChangedExtensions.RegisterValueChangedCallback<float>((INotifyValueChanged<float>)(object)slider, (EventCallback<ChangeEvent<float>>)delegate(ChangeEvent<float> e)
			{
				float num = (integer ? ((float)ValueParsing.SnapInteger(e.newValue)) : ValueParsing.RoundToStep(e.newValue, low, high));
				((BaseField<float>)(object)slider).SetValueWithoutNotify(num);
				((TextElement)valueLabel).text = ValueParsing.FormatSlider(num, integer);
				if (!Mathf.Approximately(num, get()))
				{
					set(num);
				}
			});
			val.Add((VisualElement)(object)valueLabel);
			val.Add((VisualElement)(object)slider);
			((VisualElement)row).Add(val);
			refresh = delegate
			{
				float num = get();
				((BaseField<float>)(object)slider).SetValueWithoutNotify(num);
				((TextElement)valueLabel).text = ValueParsing.FormatSlider(num, integer);
			};
			refresh();
			return slider;
		}

		public static DropdownField Dropdown(SettingRow row, List<string> labels, Func<int> getIndex, Func<string> currentLabel, Action<int> setIndex, VisualElement skinRoot, out Action refresh)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			DropdownField dropdown = new DropdownField(labels, -1, (Func<string, string>)null, (Func<string, string>)null);
			((VisualElement)dropdown).AddToClassList("options-text");
			((VisualElement)dropdown).AddToClassList("setting-dropdown");
			((CallbackEventHandler)dropdown).RegisterCallback<PointerDownEvent>((EventCallback<PointerDownEvent>)delegate
			{
				skinRoot.schedule.Execute((Action)delegate
				{
					SkinOpenDropdown(skinRoot);
				});
			}, (TrickleDown)0);
			((CallbackEventHandler)dropdown).RegisterCallback<NavigationSubmitEvent>((EventCallback<NavigationSubmitEvent>)delegate
			{
				skinRoot.schedule.Execute((Action)delegate
				{
					SkinOpenDropdown(skinRoot);
				});
			}, (TrickleDown)0);
			INotifyValueChangedExtensions.RegisterValueChangedCallback<string>((INotifyValueChanged<string>)(object)dropdown, (EventCallback<ChangeEvent<string>>)delegate
			{
				int num = labels.IndexOf(((BaseField<string>)(object)dropdown).value);
				if (num >= 0)
				{
					setIndex(num);
				}
			});
			((VisualElement)row).Add((VisualElement)(object)dropdown);
			refresh = delegate
			{
				int num = getIndex();
				((BaseField<string>)(object)dropdown).SetValueWithoutNotify((num >= 0) ? labels[num] : currentLabel());
			};
			refresh();
			return dropdown;
		}

		private static void SkinOpenDropdown(VisualElement skinRoot)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			IPanel panel = skinRoot.panel;
			VisualElement val = ((panel != null) ? UQueryExtensions.Q(panel.visualTree, (string)null, "unity-base-dropdown") : null);
			if (val == null || val.ClassListContains("trash-dropdown-skinned"))
			{
				return;
			}
			val.AddToClassList("trash-dropdown-skinned");
			int num = 0;
			while (true)
			{
				int num2 = num;
				VisualElementStyleSheetSet styleSheets = skinRoot.styleSheets;
				if (num2 < ((VisualElementStyleSheetSet)(ref styleSheets)).count)
				{
					styleSheets = val.styleSheets;
					VisualElementStyleSheetSet styleSheets2 = skinRoot.styleSheets;
					((VisualElementStyleSheetSet)(ref styleSheets)).Add(((VisualElementStyleSheetSet)(ref styleSheets2))[num]);
					num++;
					continue;
				}
				break;
			}
		}

		public static TextField Text(SettingRow row, Func<string> get, Func<string, bool> commit, out Action refresh)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0037: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			VisualElement val = new VisualElement();
			val.AddToClassList("setting-control");
			TextField val2 = new TextField();
			((TextInputBaseField<string>)val2).isDelayed = true;
			TextField field = val2;
			((VisualElement)field).AddToClassList("options-text");
			((VisualElement)field).style.flexGrow = StyleFloat.op_Implicit(1f);
			Action update = delegate
			{
				((BaseField<string>)(object)field).SetValueWithoutNotify(get());
			};
			INotifyValueChangedExtensions.RegisterValueChangedCallback<string>((INotifyValueChanged<string>)(object)field, (EventCallback<ChangeEvent<string>>)delegate(ChangeEvent<string> e)
			{
				if (!commit(e.newValue))
				{
					update();
				}
			});
			val.Add((VisualElement)(object)field);
			((VisualElement)row).Add(val);
			update();
			refresh = update;
			return field;
		}

		public static Label ReadOnly(SettingRow row, Func<string> text, out Action refresh)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			VisualElement val = new VisualElement();
			val.AddToClassList("setting-control");
			Label label = new Label();
			((VisualElement)label).AddToClassList("options-text");
			((VisualElement)label).style.opacity = StyleFloat.op_Implicit(0.7f);
			val.Add((VisualElement)(object)label);
			((VisualElement)row).Add(val);
			Action action = delegate
			{
				((TextElement)label).text = text();
			};
			action();
			refresh = action;
			return label;
		}

		public static Label Note(SettingRow row, string text)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			Label val = new Label(text);
			((VisualElement)val).AddToClassList("options-text");
			((VisualElement)val).style.opacity = StyleFloat.op_Implicit(0.7f);
			((VisualElement)val).style.marginLeft = StyleLength.op_Implicit(12f);
			((VisualElement)val).style.display = StyleEnum<DisplayStyle>.op_Implicit((DisplayStyle)1);
			((VisualElement)row).Add((VisualElement)(object)val);
			return val;
		}

		public static void Heading(VisualElement parent, string text)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			Label val = new Label(text);
			((VisualElement)val).AddToClassList("options-text");
			((VisualElement)val).style.unityFontStyleAndWeight = StyleEnum<FontStyle>.op_Implicit((FontStyle)1);
			((VisualElement)val).style.marginTop = StyleLength.op_Implicit(18f);
			((VisualElement)val).style.marginBottom = StyleLength.op_Implicit(6f);
			parent.Add((VisualElement)(object)val);
		}

		public static void Message(VisualElement parent, string text)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			Label val = new Label(text);
			((VisualElement)val).AddToClassList("options-text");
			((VisualElement)val).style.marginTop = StyleLength.op_Implicit(24f);
			((VisualElement)val).style.unityTextAlign = StyleEnum<TextAnchor>.op_Implicit((TextAnchor)4);
			parent.Add((VisualElement)(object)val);
		}
	}
	internal sealed class SaveSchedule
	{
		private readonly float _interval;

		private float _due;

		public bool Dirty { get; private set; }

		public SaveSchedule(float interval = 1f)
		{
			_interval = interval;
		}

		public void MarkDirty(float now)
		{
			if (!Dirty)
			{
				Dirty = true;
				_due = now + _interval;
			}
		}

		public bool ShouldSave(float now)
		{
			if (Dirty)
			{
				return now >= _due;
			}
			return false;
		}

		public void Saved()
		{
			Dirty = false;
		}
	}
	internal static class SettingEditors
	{
		public static Action Build(VisualElement parent, SettingInfo setting, VisualElement skinRoot, Action changed)
		{
			ConfigEntryBase entry = setting.Entry;
			Type type = entry.SettingType;
			ConfigDescription description = entry.Description;
			AcceptableValueBase acceptable = ((description != null) ? description.AcceptableValues : null);
			SettingRow val = Rows.Row(setting.Name, setting.Description);
			Label restart = null;
			Func<object, bool> set = delegate(object value)
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				if (!ConfigWriter.Set(entry, value))
				{
					changed();
					return false;
				}
				if (restart != null)
				{
					((VisualElement)restart).style.display = StyleEnum<DisplayStyle>.op_Implicit((DisplayStyle)0);
				}
				changed();
				return true;
			};
			List<object> list = ListValues(acceptable);
			EditorKind editorKind = EditorKinds.Choose(type, type == typeof(KeyboardShortcut), (list != null) ? Acceptable.List : (IsRange(acceptable) ? Acceptable.Range : Acceptable.None), list?.Count ?? 0);
			Action refresh;
			switch (editorKind)
			{
			case EditorKind.Toggle:
				Rows.Cycle(val, () => (!(bool)entry.BoxedValue) ? "Off" : "On", delegate
				{
					set(!(bool)entry.BoxedValue);
				}, delegate
				{
					set(!(bool)entry.BoxedValue);
				}, out refresh);
				break;
			case EditorKind.Cycle:
			{
				List<object> choices2 = list ?? Enum.GetValues(type).Cast<object>().ToList();
				Rows.Cycle(val, () => Label(entry.BoxedValue, type), delegate
				{
					set(choices2[Picker.Wrap(IndexOf(choices2, entry.BoxedValue) + 1, choices2.Count)]);
				}, delegate
				{
					set(choices2[Picker.Wrap(IndexOf(choices2, entry.BoxedValue) - 1, choices2.Count)]);
				}, out refresh);
				break;
			}
			case EditorKind.Dropdown:
			{
				List<object> choices = list ?? Enum.GetValues(type).Cast<object>().ToList();
				List<string> labels = choices.Select((object c) => Label(c, type)).ToList();
				Rows.Dropdown(val, labels, () => IndexOf(choices, entry.BoxedValue), () => Label(entry.BoxedValue, type), delegate(int i)
				{
					set(choices[i]);
				}, skinRoot, out refresh);
				break;
			}
			case EditorKind.SliderInt:
			case EditorKind.Slider:
			{
				(object Min, object Max) tuple = Range(acceptable);
				object item = tuple.Min;
				object item2 = tuple.Max;
				bool integer = editorKind == EditorKind.SliderInt;
				Rows.Slider(val, Convert.ToSingle(item, CultureInfo.InvariantCulture), Convert.ToSingle(item2, CultureInfo.InvariantCulture), integer, () => Convert.ToSingle(entry.BoxedValue, CultureInfo.InvariantCulture), delegate(float v)
				{
					set(Convert.ChangeType(integer ? ValueParsing.SnapInteger(v) : ((double)v), type, CultureInfo.InvariantCulture));
				}, out refresh);
				break;
			}
			case EditorKind.NumberText:
			{
				Rows.Text(val, () => ValueParsing.Format(entry.BoxedValue), (string text) => ValueParsing.TryParseNumber(text, type, out var value) && set(value), out refresh);
				break;
			}
			case EditorKind.Text:
				Rows.Text(val, () => ((string)entry.BoxedValue) ?? "", (string text) => set(text), out refresh);
				break;
			case EditorKind.Key:
				KeyRebind.Create(val, entry, set, out refresh);
				break;
			default:
				Rows.ReadOnly(val, () => entry.GetSerializedValue() + "  (edit in the config file)", out refresh);
				break;
			}
			if (setting.RestartRequired)
			{
				restart = Rows.Note(val, "restart needed");
			}
			if (setting.ReadOnly)
			{
				((VisualElement)val).SetEnabled(false);
			}
			parent.Add((VisualElement)(object)val);
			return refresh;
		}

		public static void BuildBroken(VisualElement parent, SettingInfo setting)
		{
			SettingRow val = Rows.Row(setting.Name, setting.Description);
			Rows.ReadOnly(val, () => "can't edit here", out var _);
			parent.Add((VisualElement)(object)val);
		}

		private static List<object> ListValues(AcceptableValueBase acceptable)
		{
			Type type = ((object)acceptable)?.GetType();
			if (type == null || !type.IsGenericType || type.GetGenericTypeDefinition() != typeof(AcceptableValueList<>))
			{
				return null;
			}
			return ((Array)type.GetProperty("AcceptableValues").GetValue(acceptable)).Cast<object>().ToList();
		}

		private static bool IsRange(AcceptableValueBase acceptable)
		{
			Type type = ((object)acceptable)?.GetType();
			if (type != null && type.IsGenericType)
			{
				return type.GetGenericTypeDefinition() == typeof(AcceptableValueRange<>);
			}
			return false;
		}

		private static (object Min, object Max) Range(AcceptableValueBase acceptable)
		{
			Type type = ((object)acceptable).GetType();
			return (Min: type.GetProperty("MinValue").GetValue(acceptable), Max: type.GetProperty("MaxValue").GetValue(acceptable));
		}

		private static int IndexOf(List<object> choices, object value)
		{
			for (int i = 0; i < choices.Count; i++)
			{
				if (object.Equals(choices[i], value))
				{
					return i;
				}
			}
			return -1;
		}

		private static string Label(object value, Type type)
		{
			if (!type.IsEnum)
			{
				return TomlTypeConverter.ConvertToString(value, type);
			}
			return Names.Humanize(value.ToString());
		}
	}
	internal struct SettingFacts
	{
		public string Section;

		public string Name;

		public int Order;

		public bool Advanced;

		public bool Hidden;
	}
	internal sealed class SettingGroup<T>
	{
		public string Heading;

		public bool IsAdvanced;

		public List<T> Items = new List<T>();
	}
	internal static class SettingOrder
	{
		public const string AdvancedHeading = "Advanced";

		public static List<SettingGroup<T>> Group<T>(IEnumerable<T> items, Func<T, SettingFacts> facts)
		{
			List<SettingGroup<T>> list = new List<SettingGroup<T>>();
			Dictionary<string, SettingGroup<T>> dictionary = new Dictionary<string, SettingGroup<T>>(StringComparer.Ordinal);
			SettingGroup<T> settingGroup = new SettingGroup<T>
			{
				Heading = "Advanced",
				IsAdvanced = true
			};
			foreach (T item in items)
			{
				SettingFacts settingFacts = facts(item);
				if (settingFacts.Hidden)
				{
					continue;
				}
				if (settingFacts.Advanced)
				{
					settingGroup.Items.Add(item);
					continue;
				}
				string text = settingFacts.Section ?? "";
				if (!dictionary.TryGetValue(text, out var value))
				{
					value = new SettingGroup<T>
					{
						Heading = text
					};
					dictionary.Add(text, value);
					list.Add(value);
				}
				value.Items.Add(item);
			}
			if (settingGroup.Items.Count > 0)
			{
				list.Add(settingGroup);
			}
			foreach (SettingGroup<T> item2 in list)
			{
				item2.Items = item2.Items.OrderByDescending((T i) => facts(i).Order).ThenBy<T, string>((T i) => facts(i).Name, StringComparer.OrdinalIgnoreCase).ToList();
			}
			return list;
		}

		public static bool AnyVisible<T>(IEnumerable<T> items, Func<T, SettingFacts> facts)
		{
			return items.Any((T i) => !facts(i).Hidden);
		}
	}
	internal sealed class ModInfo
	{
		public string Guid;

		public string Name;

		public string Version;

		public List<SettingInfo> Settings = new List<SettingInfo>();
	}
	internal sealed class SettingInfo
	{
		public ModInfo Mod;

		public ConfigEntryBase Entry;

		public string Section;

		public string Name;

		public string Description;

		public int Order;

		public bool ReadOnly;

		public bool Advanced;

		public bool Hidden;

		public bool RestartRequired;

		public SettingFacts Facts => new SettingFacts
		{
			Section = Section,
			Name = Name,
			Order = Order,
			Advanced = Advanced,
			Hidden = Hidden
		};
	}
	internal static class SettingsRegistry
	{
		private const BindingFlags AnyField = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static readonly HashSet<string> LoggedFailures = new HashSet<string>();

		public static List<ModInfo> Collect()
		{
			List<ModInfo> list = new List<ModInfo>();
			foreach (PluginInfo value in Chainloader.PluginInfos.Values)
			{
				if ((Object)(object)((value != null) ? value.Instance : null) == (Object)null)
				{
					continue;
				}
				try
				{
					ModInfo modInfo = new ModInfo
					{
						Guid = value.Metadata.GUID,
						Name = value.Metadata.Name,
						Version = value.Metadata.Version.ToString()
					};
					foreach (ConfigFile item in ConfigFiles(value.Instance))
					{
						foreach (ConfigEntryBase value2 in ((IDictionary<ConfigDefinition, ConfigEntryBase>)item).Values)
						{
							modInfo.Settings.Add(Describe(modInfo, value2));
						}
					}
					if (SettingOrder.AnyVisible(modInfo.Settings, (SettingInfo s) => s.Facts))
					{
						list.Add(modInfo);
					}
				}
				catch (Exception arg)
				{
					BepInPlugin metadata = value.Metadata;
					string text = ((metadata != null) ? metadata.GUID : null) ?? "?";
					if (LoggedFailures.Add(text))
					{
						Plugin.Log.LogWarning((object)$"Couldn't read the settings of {text}; it's left out of the Mods tab. {arg}");
					}
				}
			}
			return list.OrderBy<ModInfo, string>((ModInfo m) => m.Name, StringComparer.OrdinalIgnoreCase).ToList();
		}

		private static IEnumerable<ConfigFile> ConfigFiles(BaseUnityPlugin plugin)
		{
			HashSet<ConfigFile> seen = new HashSet<ConfigFile> { plugin.Config };
			yield return plugin.Config;
			Type type = ((object)plugin).GetType();
			while (type != null && type != typeof(BaseUnityPlugin))
			{
				FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (!(fieldInfo.FieldType != typeof(ConfigFile)))
					{
						BaseUnityPlugin obj = (fieldInfo.IsStatic ? null : plugin);
						object? value = fieldInfo.GetValue(obj);
						ConfigFile val = (ConfigFile)((value is ConfigFile) ? value : null);
						if (val != null && seen.Add(val))
						{
							yield return val;
						}
					}
				}
				type = type.BaseType;
			}
		}

		private static SettingInfo Describe(ModInfo mod, ConfigEntryBase entry)
		{
			SettingInfo obj = new SettingInfo
			{
				Mod = mod,
				Entry = entry,
				Section = entry.Definition.Section,
				Name = Names.Humanize(entry.Definition.Key)
			};
			ConfigDescription description = entry.Description;
			obj.Description = ((description != null) ? description.Description : null);
			SettingInfo settingInfo = obj;
			ConfigDescription description2 = entry.Description;
			object[] array = ((description2 != null) ? description2.Tags : null);
			if (array == null)
			{
				return settingInfo;
			}
			object[] array2 = array;
			foreach (object obj2 in array2)
			{
				if (obj2 != null)
				{
					settingInfo.Hidden |= Read<bool?>(obj2, "Browsable") == false;
					settingInfo.Section = Read<string>(obj2, "Category") ?? settingInfo.Section;
					settingInfo.Name = Read<string>(obj2, "DispName") ?? settingInfo.Name;
					settingInfo.Description = Read<string>(obj2, "Description") ?? settingInfo.Description;
					settingInfo.Order = Read<int?>(obj2, "Order") ?? settingInfo.Order;
					settingInfo.ReadOnly |= Read<bool?>(obj2, "ReadOnly") == true;
					settingInfo.Advanced |= Read<bool?>(obj2, "IsAdvanced") == true;
					settingInfo.RestartRequired |= Read<bool?>(obj2, "RestartRequired") == true;
				}
			}
			return settingInfo;
		}

		private static T Read<T>(object tag, string name)
		{
			Type type = tag.GetType();
			FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public);
			object value;
			if (field != null)
			{
				value = field.GetValue(tag);
			}
			else
			{
				PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public);
				if (property == null || !property.CanRead)
				{
					return default(T);
				}
				value = property.GetValue(tag);
			}
			if (value is T)
			{
				return (T)value;
			}
			return default(T);
		}
	}
	internal static class ValueParsing
	{
		private static readonly CultureInfo Inv = CultureInfo.InvariantCulture;

		public static bool TryParseNumber(string text, Type type, out object value)
		{
			value = null;
			if (string.IsNullOrWhiteSpace(text))
			{
				return false;
			}
			text = text.Trim();
			int result;
			if (type == typeof(int))
			{
				return Wrap(int.TryParse(text, NumberStyles.Integer, Inv, out result), result, out value);
			}
			long result2;
			if (type == typeof(long))
			{
				return Wrap(long.TryParse(text, NumberStyles.Integer, Inv, out result2), result2, out value);
			}
			short result3;
			if (type == typeof(short))
			{
				return Wrap(short.TryParse(text, NumberStyles.Integer, Inv, out result3), result3, out value);
			}
			byte result4;
			if (type == typeof(byte))
			{
				return Wrap(byte.TryParse(text, NumberStyles.Integer, Inv, out result4), result4, out value);
			}
			sbyte result5;
			if (type == typeof(sbyte))
			{
				return Wrap(sbyte.TryParse(text, NumberStyles.Integer, Inv, out result5), result5, out value);
			}
			uint result6;
			if (type == typeof(uint))
			{
				return Wrap(uint.TryParse(text, NumberStyles.Integer, Inv, out result6), result6, out value);
			}
			ushort result7;
			if (type == typeof(ushort))
			{
				return Wrap(ushort.TryParse(text, NumberStyles.Integer, Inv, out result7), result7, out value);
			}
			ulong result8;
			if (type == typeof(ulong))
			{
				return Wrap(ulong.TryParse(text, NumberStyles.Integer, Inv, out result8), result8, out value);
			}
			float result9;
			if (type == typeof(float))
			{
				return Wrap(float.TryParse(text, NumberStyles.Float, Inv, out result9) && !float.IsNaN(result9) && !float.IsInfinity(result9), result9, out value);
			}
			double result10;
			if (type == typeof(double))
			{
				return Wrap(double.TryParse(text, NumberStyles.Float, Inv, out result10) && !double.IsNaN(result10) && !double.IsInfinity(result10), result10, out value);
			}
			decimal result11;
			if (type == typeof(decimal))
			{
				return Wrap(decimal.TryParse(text, NumberStyles.Number | NumberStyles.AllowExponent, Inv, out result11), result11, out value);
			}
			return false;
		}

		private static bool Wrap<T>(bool ok, T parsed, out object value)
		{
			value = (ok ? ((object)parsed) : null);
			return ok;
		}

		public static bool InRange(object value, object min, object max)
		{
			IComparable comparable = (IComparable)value;
			if (comparable.CompareTo(min) >= 0)
			{
				return comparable.CompareTo(max) <= 0;
			}
			return false;
		}

		public static double SnapInteger(double value)
		{
			return Math.Round(value, MidpointRounding.AwayFromZero);
		}

		public static float RoundToStep(float value, float low, float high)
		{
			double num = Math.Pow(10.0, Math.Floor(Math.Log10(Math.Max(high - low, 1E-06))) - 2.0);
			double val = Math.Round((double)value / num) * num;
			return (float)Math.Min(high, Math.Max(low, val));
		}

		public static string Format(object value)
		{
			object obj;
			if (!(value is IFormattable formattable))
			{
				obj = value?.ToString();
				if (obj == null)
				{
					return "";
				}
			}
			else
			{
				obj = formattable.ToString(null, Inv);
			}
			return (string)obj;
		}

		public static string FormatSlider(float value, bool integer)
		{
			return value.ToString(integer ? "0" : "0.##", Inv);
		}
	}
}
namespace ModSettings.Patches
{
	[HarmonyPatch(typeof(OptionsUI), "OnEnable")]
	internal static class OptionsEnablePatch
	{
		private static bool _logged;

		private static void Postfix(OptionsUI __instance)
		{
			try
			{
				ModsTabInstaller.Install(__instance);
			}
			catch (Exception arg)
			{
				if (!_logged)
				{
					_logged = true;
					Plugin.Log.LogError((object)$"Couldn't add the Mods tab; Options is unchanged. {arg}");
				}
			}
		}
	}
	[HarmonyPatch(typeof(OptionsUI), "OnDisable")]
	internal static class OptionsDisablePatch
	{
		private static void Postfix(OptionsUI __instance)
		{
			try
			{
				ModsTabInstaller.Closed(__instance);
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Mods tab close failed. {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(OptionsUI), "CycleTab")]
	internal static class OptionsCycleTabPatch
	{
		private static bool Prefix()
		{
			return !KeyRebind.Listening;
		}
	}
	[HarmonyPatch(typeof(MenuScene), "OnNavigationCancel")]
	internal static class MenuSceneCancelPatch
	{
		private static bool Prefix()
		{
			return !KeyRebind.ConsumesCancel;
		}
	}
}