Decompiled source of Mod Config Menu v0.3.5

plugins/ModConfigMenu.dll

Decompiled 23 minutes ago
using System;
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.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using Microsoft.CodeAnalysis;
using ModConfigMenu.Logic;
using ModConfigMenu.Patches;
using Sons.Gui;
using Sons.Gui.Options;
using Sons.UiElements;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Localization;
using UnityEngine.Localization.Settings;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("ModConfigMenu")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.5.0")]
[assembly: AssemblyInformationalVersion("0.3.5+629d5c2ab375995bfaea894277ab03fcee190216")]
[assembly: AssemblyProduct("ModConfigMenu")]
[assembly: AssemblyTitle("ModConfigMenu")]
[assembly: AssemblyVersion("0.3.5.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
internal static class SettingMove
{
	internal static void Move(ConfigFile config, string oldSection, string oldKey, ConfigEntryBase to)
	{
		bool saveOnConfigSet = config.SaveOnConfigSet;
		config.SaveOnConfigSet = false;
		try
		{
			ConfigEntry<string> val = config.Bind<string>(oldSection, oldKey, "\u0001", "Old place of a moved setting.");
			bool num = val.Value != "\u0001";
			if (num)
			{
				to.SetSerializedValue(((ConfigEntryBase)val).GetSerializedValue());
			}
			config.Remove(((ConfigEntryBase)val).Definition);
			if (num)
			{
				config.Save();
			}
		}
		finally
		{
			config.SaveOnConfigSet = saveOnConfigSet;
		}
	}
}
namespace ModConfigMenu
{
	[BepInPlugin("aznan.sotf.modconfigmenu", "ModConfigMenu", "0.3.5")]
	public class Plugin : BasePlugin
	{
		internal const string Version = "0.3.5";

		internal static ManualLogSource Logger;

		internal static ConfigEntry<bool> FullLogging;

		internal static ConfigEntry<string> TabText;

		internal static ConfigEntry<string> DefaultText;

		internal static ConfigEntry<string> PressKeyText;

		internal static ConfigEntry<string> OnText;

		internal static ConfigEntry<string> OffText;

		internal static ConfigEntry<string> NoSettingsText;

		internal static ConfigEntry<string> SavedText;

		internal static ConfigEntry<string> InvalidText;

		internal static ConfigEntry<string> SearchText;

		internal static ConfigEntry<string> NoMatchText;

		internal static ConfigEntry<string> ResetAllText;

		internal static ConfigEntry<string> ConfirmResetAllText;

		internal static ConfigEntry<string> ResetDoneText;

		internal static ConfigEntry<string> SelectedMark;

		internal static ConfigEntry<string> ModifiedMark;

		internal static ConfigEntry<string> ExpandedMark;

		internal static ConfigEntry<string> CollapsedMark;

		internal static ConfigEntry<string> FirstSections;

		internal static ConfigEntry<string> LastSections;

		internal static ConfigEntry<int> TabPosition;

		internal static ConfigEntry<int> SliderDecimals;

		internal static ConfigEntry<int> SliderSteps;

		internal static ConfigEntry<int> CollapseSectionsOver;

		internal static ConfigEntry<float> ModListWidth;

		internal static ConfigEntry<float> ColumnGap;

		internal static ConfigEntry<bool> ReadableNames;

		internal static ConfigEntry<bool> HideModsWithoutSettings;

		internal static ConfigEntry<bool> ShowVersions;

		private const string Automatic = "Empty = automatic, in the game's language.";

		private static string LocaleCode
		{
			get
			{
				Locale selectedLocale = LocalizationSettings.SelectedLocale;
				if (selectedLocale == null)
				{
					return null;
				}
				return selectedLocale.Identifier.Code;
			}
		}

		internal static void Trace(string message)
		{
			if (FullLogging.Value)
			{
				Logger.LogInfo((object)message);
			}
		}

		private static void Refuse(ConfigEntry<int> e, Func<int, bool> breaks, string why)
		{
			Check();
			e.SettingChanged += delegate
			{
				Check();
			};
			void Check()
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Expected O, but got Unknown
				if (breaks(e.Value))
				{
					ManualLogSource logger = Logger;
					bool flag = default(bool);
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(28, 5, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((ConfigEntryBase)e).Definition.Section);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((ConfigEntryBase)e).Definition.Key);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" = ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(e.Value);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" refused (");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(why);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("); back to ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<object>(((ConfigEntryBase)e).DefaultValue);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
					}
					logger.LogWarning(val);
					e.Value = (int)((ConfigEntryBase)e).DefaultValue;
				}
			}
		}

		public override void Load()
		{
			//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d4: Expected O, but got Unknown
			Logger = ((BasePlugin)this).Log;
			Texts.SelfCheck();
			Controls.SelfCheck();
			Names.SelfCheck();
			TabPosition = ((BasePlugin)this).Config.Bind<int>("General", "TabPosition", -1, "Place of the Mods tab in the game's Settings screen tab bar, counted from 0 at the left. -1 = after the last game tab. Advised: -1 to 20.");
			ModListWidth = ((BasePlugin)this).Config.Bind<float>("Layout", "ModListWidth", 0.3f, "Share of the page width taken by the mod list on the left. Advised: 0.1 to 0.6.");
			ColumnGap = ((BasePlugin)this).Config.Bind<float>("Layout", "ColumnGap", 40f, "Space between the mod list and the settings, in pixels. Advised: 0 to 300.");
			ReadableNames = ((BasePlugin)this).Config.Bind<bool>("Layout", "ReadableNames", true, "True = setting names shown as words (\"EnemiesFrozen\" -> \"Enemies frozen\"). False = names exactly as in the settings file.");
			HideModsWithoutSettings = ((BasePlugin)this).Config.Bind<bool>("Layout", "HideModsWithoutSettings", true, "True = mods that have no setting are left out of the list.");
			ShowVersions = ((BasePlugin)this).Config.Bind<bool>("Layout", "ShowVersions", true, "True = each mod's version is shown after its name in the mod list.");
			CollapseSectionsOver = ((BasePlugin)this).Config.Bind<int>("Layout", "CollapseSectionsOver", 12, "Sections with more settings than this start folded (click the title to unfold). 0 = never folded. Advised: 0 to 1000.");
			FirstSections = ((BasePlugin)this).Config.Bind<string>("Layout", "FirstSections", "General", "Sections shown first, in this order, separated by commas; the others follow in the mod's own order.");
			LastSections = ((BasePlugin)this).Config.Bind<string>("Layout", "LastSections", "Texts,Multiplayer,Performance,Debug", "Sections shown last, in this order, separated by commas (after the mod's own sections).");
			SliderDecimals = ((BasePlugin)this).Config.Bind<int>("Layout", "SliderDecimals", 2, "Decimals kept when a slider sets a decimal number. Advised: 0 to 6.");
			SliderSteps = ((BasePlugin)this).Config.Bind<int>("Layout", "SliderSteps", 20, "Steps from one end of a slider to the other with the keyboard or a gamepad. Advised: 2 to 1000.");
			Refuse(SliderDecimals, (int d) => d < 0 || d > 15, "a number can only be rounded to 0 to 15 decimals");
			Refuse(SliderSteps, (int n) => n < 1, "a slider needs at least one step");
			TabText = ((BasePlugin)this).Config.Bind<string>("Texts", "TabText", "", "Text of the Mods tab in the game's Settings screen (pause menu and title screen). Empty = automatic, in the game's language.");
			DefaultText = ((BasePlugin)this).Config.Bind<string>("Texts", "DefaultText", "", "Text of the button that puts a setting back to its default value. Empty = automatic, in the game's language.");
			PressKeyText = ((BasePlugin)this).Config.Bind<string>("Texts", "PressKeyText", "", "Shown while waiting for the new key of a key setting. Empty = automatic, in the game's language.");
			OnText = ((BasePlugin)this).Config.Bind<string>("Texts", "OnText", "", "Shown for a yes/no setting that is on. Empty = automatic, in the game's language.");
			OffText = ((BasePlugin)this).Config.Bind<string>("Texts", "OffText", "", "Shown for a yes/no setting that is off. Empty = automatic, in the game's language.");
			NoSettingsText = ((BasePlugin)this).Config.Bind<string>("Texts", "NoSettingsText", "", "Shown for a mod that has no settings. Empty = automatic, in the game's language.");
			SavedText = ((BasePlugin)this).Config.Bind<string>("Texts", "SavedText", "", "Shown after a change, followed by the settings file name. Empty = automatic, in the game's language.");
			InvalidText = ((BasePlugin)this).Config.Bind<string>("Texts", "InvalidText", "", "Shown when typed text does not fit the setting. Empty = automatic, in the game's language.");
			SearchText = ((BasePlugin)this).Config.Bind<string>("Texts", "SearchText", "", "Label of the search field above the settings. Empty = automatic, in the game's language.");
			NoMatchText = ((BasePlugin)this).Config.Bind<string>("Texts", "NoMatchText", "", "Shown when no setting matches the search. Empty = automatic, in the game's language.");
			ResetAllText = ((BasePlugin)this).Config.Bind<string>("Texts", "ResetAllText", "", "Button that puts every setting of the shown mod back to default. Empty = the game's own Reset text.");
			ConfirmResetAllText = ((BasePlugin)this).Config.Bind<string>("Texts", "ConfirmResetAllText", "", "Asked after a first click on the reset-all button, followed by the mod's name. Empty = automatic, in the game's language.");
			ResetDoneText = ((BasePlugin)this).Config.Bind<string>("Texts", "ResetDoneText", "", "Shown after a reset-all, followed by how many settings changed. Empty = automatic, in the game's language.");
			SelectedMark = ((BasePlugin)this).Config.Bind<string>("Texts", "SelectedMark", "> ", "Put before the name of the mod whose settings are shown.");
			ModifiedMark = ((BasePlugin)this).Config.Bind<string>("Texts", "ModifiedMark", "* ", "Put before the name of a setting that is not at its default value. Empty = no mark.");
			ExpandedMark = ((BasePlugin)this).Config.Bind<string>("Texts", "ExpandedMark", "[-] ", "Put before the title of an unfolded section.");
			CollapsedMark = ((BasePlugin)this).Config.Bind<string>("Texts", "CollapsedMark", "[+] ", "Put before the title of a folded section.");
			FullLogging = ((BasePlugin)this).Config.Bind<bool>("Debug", "FullLogging", false, "True = the BepInEx log gets every step useful to diagnose a problem (decisions, values read, object aimed at, failures with their cause). False = only loading, version and errors.");
			SettingMove.Move(((BasePlugin)this).Config, "General", "TabText", (ConfigEntryBase)(object)TabText);
			((BasePlugin)this).Config.SettingChanged += delegate
			{
				ModsPage.OwnSettingChanged();
			};
			ClassInjector.RegisterTypeInIl2Cpp<PageDriver>();
			new Harmony("aznan.sotf.modconfigmenu").PatchAll();
			ManualLogSource logger = Logger;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(21, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("ModConfigMenu ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("0.3.5");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded");
			}
			logger.LogInfo(val);
		}

		internal static string Text(ConfigEntry<string> setting, string modKey)
		{
			if (string.IsNullOrEmpty(setting?.Value))
			{
				return Texts.Get(LocaleCode, modKey);
			}
			return setting.Value;
		}
	}
	internal static class Settings
	{
		internal record Mod(string Name, string Version, string Guid, ConfigFile Config);

		internal static List<Mod> LoadedMods()
		{
			return ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.Values.Select(delegate(PluginInfo p)
			{
				string name = p.Metadata.Name;
				string? version = ((object)p.Metadata.Version)?.ToString();
				string gUID = p.Metadata.GUID;
				object instance = p.Instance;
				object obj = ((instance is BasePlugin) ? instance : null);
				return new Mod(name, version, gUID, (obj != null) ? ((BasePlugin)obj).Config : null);
			}).OrderBy<Mod, string>((Mod m) => m.Name, StringComparer.OrdinalIgnoreCase).ToList();
		}

		internal static IEnumerable<ConfigEntryBase> Entries(ConfigFile config)
		{
			if (config != null)
			{
				return ((IEnumerable<KeyValuePair<ConfigDefinition, ConfigEntryBase>>)config).Select((KeyValuePair<ConfigDefinition, ConfigEntryBase> kv) => kv.Value);
			}
			return Enumerable.Empty<ConfigEntryBase>();
		}

		internal static List<IGrouping<string, ConfigEntryBase>> Sections(ConfigFile config)
		{
			List<IGrouping<string, ConfigEntryBase>> groups = (from e in Entries(config)
				group e by e.Definition.Section).ToList();
			return (from k in Names.SectionOrder(groups.Select((IGrouping<string, ConfigEntryBase> g) => g.Key), Plugin.FirstSections.Value, Plugin.LastSections.Value)
				select groups.First((IGrouping<string, ConfigEntryBase> g) => g.Key == k)).ToList();
		}

		internal static bool IsDefault(ConfigEntryBase e)
		{
			return object.Equals(e.BoxedValue, e.DefaultValue);
		}

		internal static ControlKind Kind(ConfigEntryBase e)
		{
			double min;
			double max;
			return Controls.Pick(e.SettingType == typeof(bool), IsKey(e), Choices(e) != null, Range(e, out min, out max));
		}

		internal static bool IsKey(ConfigEntryBase e)
		{
			if (!(e.SettingType == typeof(KeyCode)))
			{
				return e.SettingType.Name == "KeyboardShortcut";
			}
			return true;
		}

		internal static bool IsShortcut(ConfigEntryBase e)
		{
			return e.SettingType != typeof(KeyCode);
		}

		internal static bool IsWholeNumber(ConfigEntryBase e)
		{
			if (!(e.SettingType == typeof(int)) && !(e.SettingType == typeof(long)) && !(e.SettingType == typeof(short)) && !(e.SettingType == typeof(byte)) && !(e.SettingType == typeof(uint)) && !(e.SettingType == typeof(ulong)) && !(e.SettingType == typeof(ushort)))
			{
				return e.SettingType == typeof(sbyte);
			}
			return true;
		}

		internal static List<string> Choices(ConfigEntryBase e)
		{
			Type t = e.SettingType;
			if (t.IsEnum && !t.IsDefined(typeof(FlagsAttribute), inherit: false))
			{
				return Enum.GetNames(t).ToList();
			}
			ConfigDescription description = e.Description;
			AcceptableValueBase val = ((description != null) ? description.AcceptableValues : null);
			if (val == null || !((object)val).GetType().IsGenericType || ((object)val).GetType().GetGenericTypeDefinition() != typeof(AcceptableValueList<>))
			{
				return null;
			}
			return (from object v in (Array)((object)val).GetType().GetProperty("AcceptableValues").GetValue(val)
				select TomlTypeConverter.ConvertToString(v, t)).ToList();
		}

		internal static bool Range(ConfigEntryBase e, out double min, out double max)
		{
			min = (max = 0.0);
			ConfigDescription description = e.Description;
			AcceptableValueBase val = ((description != null) ? description.AcceptableValues : null);
			if (val == null || !((object)val).GetType().IsGenericType || ((object)val).GetType().GetGenericTypeDefinition() != typeof(AcceptableValueRange<>))
			{
				return false;
			}
			min = Convert.ToDouble(((object)val).GetType().GetProperty("MinValue").GetValue(val), CultureInfo.InvariantCulture);
			max = Convert.ToDouble(((object)val).GetType().GetProperty("MaxValue").GetValue(val), CultureInfo.InvariantCulture);
			return true;
		}

		internal static bool TrySet(ConfigEntryBase e, string text)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			try
			{
				e.BoxedValue = TomlTypeConverter.ConvertToValue(text, e.SettingType);
				return true;
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(17, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("'");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' refused for ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<ConfigDefinition>(e.Definition);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				}
				logger.LogWarning(val);
				return false;
			}
		}

		internal static void SetNumber(ConfigEntryBase e, double value)
		{
			e.BoxedValue = Convert.ChangeType(value, e.SettingType, CultureInfo.InvariantCulture);
		}

		internal static void ResetToDefault(ConfigEntryBase e)
		{
			e.BoxedValue = e.DefaultValue;
		}
	}
}
namespace ModConfigMenu.Patches
{
	internal static class ModsPage
	{
		private sealed class ModEntry
		{
			internal Settings.Mod Mod;

			internal GameObject Go;

			internal TMP_Text Label;

			internal string AllText;

			internal bool HasSettings;
		}

		private sealed class Section
		{
			internal string Key;

			internal string Title;

			internal GameObject Go;

			internal GameObject Rows;

			internal TMP_Text Label;

			internal readonly List<Row> Items = new List<Row>();
		}

		private sealed class Row
		{
			internal ConfigEntryBase Entry;

			internal ConfigFile Config;

			internal GameObject Go;

			internal TMP_Text Label;

			internal string Name;

			internal string Haystack;

			internal Action Refresh;
		}

		private const string PageName = "ModConfigMenu_Page";

		private const string ModsTabName = "ModConfigMenu_Tab";

		private const string SearchBarName = "ModConfigMenu_Search";

		private const string TitlePanel = "TitlePanel";

		private const string TooltipText = "TooltipPanel/Text";

		private const string BottomBack = "Panel/LeftAnchor/BackButton";

		private const string BottomReset = "Panel/LeftAnchor/ResetButton";

		private const string LabelPanel = "LabelPanel";

		private const string RowLabel = "LabelPanel/Label";

		private const string ReadoutLabel = "SliderPanel/ReadoutLabel";

		private const string LeftArrow = "LeftButton";

		private const string RightArrow = "RightButton";

		private const string DropdownBacking = "DropdownBacking";

		private const string KeyIcon = "InputIcon";

		private const string KeyWarning = "WarnIndicator01";

		private const string DefaultButton = "ResetBindingsButton";

		private static readonly HashSet<string> GameLogic = new HashSet<string>
		{
			"OptionsGuiManager", "OptionGuiTooltipController", "LocalizeStringEvent", "LocalizedLinkText", "LinkSliderToText", "RebindingInputOptionGui", "InputGamepadMenuHelper", "InputActionMapState", "BackButton", "ResetButton",
			"ApplyButton", "GameObjectLocalizer"
		};

		private static readonly KeyCode[] AllKeys = (KeyCode[])Enum.GetValues(typeof(KeyCode));

		private static readonly HashSet<KeyCode> Modifiers = new HashSet<KeyCode>
		{
			(KeyCode)304,
			(KeyCode)303,
			(KeyCode)306,
			(KeyCode)305,
			(KeyCode)308,
			(KeyCode)307,
			(KeyCode)310,
			(KeyCode)309,
			(KeyCode)313
		};

		private static OptionsGuiManager _builtFrom;

		private static int _closedFrame = -10;

		private static GameObject _page;

		private static TMP_Text _tip;

		private static TMP_Text _searchLabel;

		private static TMP_InputField _search;

		private static Transform _modList;

		private static Transform _settingsList;

		private static RectTransform _modColumn;

		private static RectTransform _settingsColumn;

		private static RectTransform _searchBar;

		private static GameObject _resetAllButton;

		private static GameObject _pageModsTab;

		private static float _searchHeight;

		private static GameObject _sectionTemplate;

		private static GameObject _choiceRow;

		private static GameObject _sliderRow;

		private static GameObject _keyRow;

		private static GameObject _defaultButton;

		private static GameObject _inputField;

		private static string _sectionRowsName;

		private static string _gameResetText;

		private static readonly List<ModEntry> _mods = new List<ModEntry>();

		private static readonly List<Section> _sections = new List<Section>();

		private static readonly Dictionary<int, string> _modTips = new Dictionary<int, string>();

		private static readonly Dictionary<int, string> _rowTips = new Dictionary<int, string>();

		private static readonly Dictionary<string, bool> _collapsed = new Dictionary<string, bool>();

		private static Settings.Mod _shown;

		private static string _selectedGuid;

		private static string _shownTip;

		private static string _query = "";

		private static bool _resetArmed;

		private static EventSystem _events;

		private static PointerEventData _pointer;

		private static List<RaycastResult> _hits;

		private static Vector3 _lastMouse;

		private static GameObject _lastSelected;

		private static bool _gamepad;

		private static ConfigEntryBase _capturing;

		private static Row _captureRow;

		private static int _captureEndFrame = -10;

		internal static bool IsOpen
		{
			get
			{
				if ((Object)(object)_page != (Object)null)
				{
					return _page.activeSelf;
				}
				return false;
			}
		}

		internal static void AddTab(OptionsGuiManager options)
		{
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Component)options).transform.Find("TitlePanel");
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Logger.LogWarning((object)"Settings screen tab bar not found; Mods tab not added.");
				return;
			}
			Transform obj = val.Find("ModConfigMenu_Tab");
			GameObject val2 = ((obj != null) ? ((Component)obj).gameObject : null);
			if ((Object)(object)val2 == (Object)null)
			{
				GameObject val3 = null;
				int num = -1;
				for (int i = 0; i < val.childCount; i++)
				{
					if ((Object)(object)((Component)val.GetChild(i)).GetComponent<LinkTextGui>() != (Object)null)
					{
						val3 = ((Component)val.GetChild(i)).gameObject;
						num = i;
					}
				}
				if ((Object)(object)val3 == (Object)null)
				{
					Plugin.Logger.LogWarning((object)"No game tab to copy; Mods tab not added.");
					return;
				}
				val2 = Copy(val3, val);
				((Object)val2).name = "ModConfigMenu_Tab";
				int value = Plugin.TabPosition.Value;
				val2.transform.SetSiblingIndex((value >= 0) ? Math.Min(value, val.childCount - 1) : (num + 1));
				int value2 = Recolor(val2, options._activeColor, options._inactiveColor);
				OnClick(val2, delegate
				{
					OpenFrom(options);
				});
				Plugin.Trace($"Mods tab added to the Settings screen after '{((Object)val3).name}' (tab colors: active {options._activeColor}, inactive {options._inactiveColor}; {value2} parts set to inactive).");
			}
			SetButtonText(val2, Plugin.Text(Plugin.TabText, "Mods"));
		}

		private static void OpenFrom(OptionsGuiManager options)
		{
			Plugin.Trace("Mods tab clicked.");
			if (EnsureBuilt(options))
			{
				((Component)options).gameObject.SetActive(false);
				Show();
			}
		}

		private static bool EnsureBuilt(OptionsGuiManager options)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			if ((Object)(object)options == (Object)null)
			{
				Plugin.Logger.LogError((object)"Game options screen not found; Mods page not shown.");
				return false;
			}
			if ((Object)(object)_page != (Object)null && (Object)(object)_builtFrom != (Object)null && ((Il2CppObjectBase)_builtFrom).Pointer == ((Il2CppObjectBase)options).Pointer)
			{
				return true;
			}
			_builtFrom = options;
			try
			{
				_page = Build(options);
			}
			catch (Exception ex)
			{
				_page = null;
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(30, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Mods page could not be built: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val);
			}
			return (Object)(object)_page != (Object)null;
		}

		private static void Show()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			_page.SetActive(true);
			_events = EventSystem.current;
			_pointer = ((!((Object)(object)_events != (Object)null)) ? ((PointerEventData)null) : new PointerEventData(_events));
			if (_hits == null)
			{
				_hits = new List<RaycastResult>();
			}
			_lastSelected = null;
			_gamepad = ((IEnumerable<string>)Input.GetJoystickNames()).Any((string n) => !string.IsNullOrEmpty(n));
			_query = "";
			TMP_InputField search = _search;
			if (search != null)
			{
				search.SetTextWithoutNotify("");
			}
			ApplyTexts();
			ApplyLayout();
			ShowModList();
			LogLayout();
			Plugin.Trace("Mods page opened.");
		}

		internal static void Close()
		{
			if (IsOpen)
			{
				CancelCapture();
				_page.SetActive(false);
				_closedFrame = Time.frameCount;
				EventSystem events = _events;
				if (events != null)
				{
					events.SetSelectedGameObject((GameObject)null);
				}
				if ((Object)(object)_builtFrom != (Object)null)
				{
					((Component)_builtFrom).gameObject.SetActive(true);
				}
				Plugin.Trace("Mods page closed.");
			}
		}

		private static void BackToGame()
		{
			OptionsGuiManager builtFrom = _builtFrom;
			Close();
			if (!((Object)(object)builtFrom == (Object)null))
			{
				Button backButton = builtFrom._backButton;
				if ((Object)(object)backButton != (Object)null)
				{
					((UnityEvent)backButton.onClick).Invoke();
				}
				else
				{
					builtFrom.OnBack();
				}
			}
		}

		private static void GoToGameTab(string tabName)
		{
			OptionsGuiManager builtFrom = _builtFrom;
			Close();
			if (builtFrom == null)
			{
				return;
			}
			Transform obj = ((Component)builtFrom).transform.Find("TitlePanel");
			if (obj == null)
			{
				return;
			}
			Transform obj2 = obj.Find(tabName);
			if (obj2 != null)
			{
				Button component = ((Component)obj2).GetComponent<Button>();
				if (component != null)
				{
					((UnityEvent)component.onClick).Invoke();
				}
			}
		}

		internal static bool OwnsBack()
		{
			if (!IsOpen)
			{
				return Time.frameCount == _closedFrame;
			}
			return true;
		}

		internal static void OwnSettingChanged()
		{
			if (IsOpen)
			{
				ApplyLayout();
				ApplyFilter();
			}
		}

		private static GameObject Build(OptionsGuiManager options)
		{
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03de: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0556: Unknown result type (might be due to invalid IL or missing references)
			//IL_055b: Unknown result type (might be due to invalid IL or missing references)
			FindTemplates(options);
			GameObject holder;
			GameObject val = CopyAsleep(((Component)options).gameObject, out holder);
			((Object)val).name = "ModConfigMenu_Page";
			string text = GameText(val.transform.Find("Panel/LeftAnchor/BackButton"));
			_gameResetText = GameText(val.transform.Find("Panel/LeftAnchor/ResetButton"));
			GameplayOptionsGui componentInChildren = val.GetComponentInChildren<GameplayOptionsGui>(true);
			GameObject val2 = ((componentInChildren != null) ? ((Component)componentInChildren).gameObject : null);
			if ((Object)(object)val2 == (Object)null)
			{
				throw new InvalidOperationException("Gameplay options page not found in the copy");
			}
			foreach (OptionsGui componentsInChild in val.GetComponentsInChildren<OptionsGui>(true))
			{
				if ((Object)(object)((Component)componentsInChild).gameObject != (Object)(object)val2)
				{
					Object.DestroyImmediate((Object)(object)((Component)componentsInChild).gameObject);
				}
			}
			val2.SetActive(true);
			ScrollRect componentInChildren2 = val2.GetComponentInChildren<ScrollRect>(true);
			ClearNow((Transform)(object)componentInChildren2.content);
			ScrollRect component = Object.Instantiate<GameObject>(((Component)componentInChildren2).gameObject, ((Component)componentInChildren2).transform.parent).GetComponent<ScrollRect>();
			((Component)component).transform.SetSiblingIndex(((Component)componentInChildren2).transform.GetSiblingIndex());
			_modList = (Transform)(object)component.content;
			_settingsList = (Transform)(object)componentInChildren2.content;
			_modColumn = OutOfLayout(((Component)component).gameObject);
			_settingsColumn = OutOfLayout(((Component)componentInChildren2).gameObject);
			Plugin.Trace($"Layout source: list anchors {_settingsColumn.anchorMin}-{_settingsColumn.anchorMax}, offsets {_settingsColumn.offsetMin}/{_settingsColumn.offsetMax}");
			Strip(val);
			Transform val3 = val.transform.Find("TitlePanel");
			_pageModsTab = null;
			int num = 0;
			for (int i = 0; i < val3.childCount; i++)
			{
				GameObject gameObject = ((Component)val3.GetChild(i)).gameObject;
				if ((Object)(object)gameObject.GetComponent<LinkTextGui>() == (Object)null)
				{
					gameObject.SetActive(false);
					continue;
				}
				if (((Object)gameObject).name == "ModConfigMenu_Tab")
				{
					_pageModsTab = gameObject;
					OnClick(gameObject, delegate
					{
					});
					num += Recolor(gameObject, options._inactiveColor, options._activeColor);
					continue;
				}
				string tabName = ((Object)gameObject).name;
				OnClick(gameObject, delegate
				{
					GoToGameTab(tabName);
				});
				num += Recolor(gameObject, options._activeColor, options._inactiveColor);
			}
			Plugin.Trace($"Page tabs: {num} parts recolored, Mods tab {(((Object)(object)_pageModsTab != (Object)null) ? "found" : "MISSING")}.");
			Transform obj = val.transform.Find("TooltipPanel/Text");
			_tip = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null);
			OptionGuiTooltipController componentInChildren3 = ((Component)options).GetComponentInChildren<OptionGuiTooltipController>(true);
			if ((Object)(object)_tip != (Object)null && (Object)(object)componentInChildren3 != (Object)null)
			{
				Image component2 = ((Component)_tip.transform.parent).GetComponent<Image>();
				if ((Object)(object)component2 != (Object)null && componentInChildren3._initialBackgroundColorAlpha > 0f)
				{
					((Graphic)component2).color = WithAlpha(((Graphic)component2).color, componentInChildren3._initialBackgroundColorAlpha);
				}
				if (componentInChildren3._initialTextColorAlpha > 0f)
				{
					((Graphic)_tip).color = WithAlpha(((Graphic)_tip).color, componentInChildren3._initialTextColorAlpha);
				}
			}
			Transform val4 = val.transform.Find("Panel/LeftAnchor/BackButton");
			if ((Object)(object)val4 != (Object)null)
			{
				OnClick(((Component)val4).gameObject, BackToGame);
				if (!string.IsNullOrEmpty(text))
				{
					SetButtonText(((Component)val4).gameObject, text);
				}
			}
			Transform obj2 = val.transform.Find("Panel/LeftAnchor/ResetButton");
			_resetAllButton = ((obj2 != null) ? ((Component)obj2).gameObject : null);
			if ((Object)(object)_resetAllButton != (Object)null)
			{
				OnClick(_resetAllButton, ResetAllClicked);
			}
			_search = null;
			_searchHeight = 0f;
			_searchBar = OutOfLayout(Copy(_choiceRow, val2.transform));
			((Object)_searchBar).name = "ModConfigMenu_Search";
			Transform obj3 = ((Transform)_searchBar).Find("LabelPanel/Label");
			_searchLabel = ((obj3 != null) ? ((Component)obj3).GetComponent<TMP_Text>() : null);
			if ((Object)(object)_inputField != (Object)null)
			{
				_search = PutTextField(((Component)_searchBar).gameObject);
				((UnityEvent<string>)(object)_search.onValueChanged).AddListener(UnityAction<string>.op_Implicit((Action<string>)delegate(string s)
				{
					_query = (s ?? "").Trim().ToLowerInvariant();
					ApplyFilter();
				}));
				Rect rect = _choiceRow.GetComponent<RectTransform>().rect;
				float height = ((Rect)(ref rect)).height;
				_searchHeight = ((height > 1f) ? height : LayoutUtility.GetPreferredHeight(_searchBar));
			}
			else
			{
				((Component)_searchBar).gameObject.SetActive(false);
			}
			val.SetActive(false);
			val.transform.SetParent(((Component)options).transform.parent, false);
			val.transform.SetSiblingIndex(((Component)options).transform.GetSiblingIndex() + 1);
			Object.Destroy((Object)(object)holder);
			val.AddComponent<PageDriver>();
			Plugin.Trace($"Mods page built from the game's options screen (search bar height {_searchHeight}).");
			return val;
		}

		private static void FindTemplates(OptionsGuiManager options)
		{
			_choiceRow = RowOf(((Component)((Component)((Component)options).GetComponentInChildren<GameplayOptionsGui>(true)).GetComponentInChildren<SonsDropdown>(true)).transform);
			_sliderRow = RowOf(((Component)((Component)options).GetComponentInChildren<SonsSlider>(true)).transform);
			RebindingInputOptionGui componentInChildren = ((Component)options).GetComponentInChildren<RebindingInputOptionGui>(true);
			_keyRow = ((componentInChildren != null) ? ((Component)componentInChildren).gameObject : null);
			Button? obj = ((IEnumerable<Button>)((Component)options).GetComponentsInChildren<Button>(true)).FirstOrDefault((Func<Button, bool>)((Button b) => ((Object)b).name == "ResetBindingsButton"));
			_defaultButton = ((obj != null) ? ((Component)obj).gameObject : null);
			TMP_InputField? obj2 = ((IEnumerable<TMP_InputField>)Resources.FindObjectsOfTypeAll<TMP_InputField>()).FirstOrDefault((Func<TMP_InputField, bool>)delegate(TMP_InputField f)
			{
				//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)
				Scene scene = ((Component)f).gameObject.scene;
				return ((Scene)(ref scene)).IsValid();
			});
			_inputField = ((obj2 != null) ? ((Component)obj2).gameObject : null);
			_sectionTemplate = ((Component)_choiceRow.transform.parent.parent).gameObject;
			_sectionRowsName = ((Object)_choiceRow.transform.parent).name;
			DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(60, 6);
			defaultInterpolatedStringHandler.AppendLiteral("Templates: choice=");
			GameObject choiceRow = _choiceRow;
			defaultInterpolatedStringHandler.AppendFormatted((choiceRow != null) ? ((Object)choiceRow).name : null);
			defaultInterpolatedStringHandler.AppendLiteral(", slider=");
			GameObject sliderRow = _sliderRow;
			defaultInterpolatedStringHandler.AppendFormatted((sliderRow != null) ? ((Object)sliderRow).name : null);
			defaultInterpolatedStringHandler.AppendLiteral(", key=");
			GameObject keyRow = _keyRow;
			defaultInterpolatedStringHandler.AppendFormatted((keyRow != null) ? ((Object)keyRow).name : null);
			defaultInterpolatedStringHandler.AppendLiteral(", default=");
			GameObject defaultButton = _defaultButton;
			defaultInterpolatedStringHandler.AppendFormatted((defaultButton != null) ? ((Object)defaultButton).name : null);
			defaultInterpolatedStringHandler.AppendLiteral(", text=");
			GameObject inputField = _inputField;
			defaultInterpolatedStringHandler.AppendFormatted((inputField != null) ? ((Object)inputField).name : null);
			defaultInterpolatedStringHandler.AppendLiteral(", section=");
			GameObject sectionTemplate = _sectionTemplate;
			defaultInterpolatedStringHandler.AppendFormatted((sectionTemplate != null) ? ((Object)sectionTemplate).name : null);
			Plugin.Trace(defaultInterpolatedStringHandler.ToStringAndClear());
		}

		private static GameObject RowOf(Transform t)
		{
			while ((Object)(object)t != (Object)null && (Object)(object)((Component)t).GetComponent<HorizontalLayoutGroup>() == (Object)null)
			{
				t = t.parent;
			}
			if (t == null)
			{
				return null;
			}
			return ((Component)t).gameObject;
		}

		private static RectTransform OutOfLayout(GameObject go)
		{
			(go.GetComponent<LayoutElement>() ?? go.AddComponent<LayoutElement>()).ignoreLayout = true;
			return go.GetComponent<RectTransform>();
		}

		private static void ApplyLayout()
		{
			//IL_0031: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			float value = Plugin.ModListWidth.Value;
			float num = Plugin.ColumnGap.Value / 2f;
			Place(_modColumn, 0f, value, 0f, 1f, Vector2.zero, new Vector2(0f - num, 0f));
			Place(_settingsColumn, value, 1f, 0f, 1f, new Vector2(num, 0f), new Vector2(0f, 0f - _searchHeight));
			Place(_searchBar, value, 1f, 1f, 1f, new Vector2(num, 0f - _searchHeight), Vector2.zero);
		}

		private static void Place(RectTransform r, float xMin, float xMax, float yMin, float yMax, Vector2 offsetMin, Vector2 offsetMax)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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)
			if (!((Object)(object)r == (Object)null))
			{
				r.anchorMin = new Vector2(xMin, yMin);
				r.anchorMax = new Vector2(xMax, yMax);
				r.offsetMin = offsetMin;
				r.offsetMax = offsetMax;
			}
		}

		private static void ApplyTexts()
		{
			SetButtonText(_pageModsTab, Plugin.Text(Plugin.TabText, "Mods"));
			if ((Object)(object)_searchLabel != (Object)null)
			{
				_searchLabel.text = Plugin.Text(Plugin.SearchText, "Search");
			}
			if ((Object)(object)_resetAllButton != (Object)null)
			{
				SetButtonText(_resetAllButton, (!string.IsNullOrEmpty(Plugin.ResetAllText.Value)) ? Plugin.ResetAllText.Value : ((!string.IsNullOrEmpty(_gameResetText)) ? _gameResetText : Texts.Get(null, "ResetAll")));
			}
		}

		private static void ShowModList()
		{
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			Clear(_modList);
			_mods.Clear();
			_modTips.Clear();
			bool flag = default(bool);
			foreach (Settings.Mod item in Settings.LoadedMods())
			{
				List<ConfigEntryBase> list = Settings.Entries(item.Config).ToList();
				ModEntry modEntry = new ModEntry
				{
					Mod = item,
					HasSettings = (list.Count > 0),
					AllText = (item.Name + "\n" + string.Join("\n", list.Select(Haystack))).ToLowerInvariant()
				};
				try
				{
					AddModEntry(modEntry);
					_mods.Add(modEntry);
				}
				catch (Exception ex)
				{
					ManualLogSource logger = Plugin.Logger;
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(27, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("List entry for ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(item.Guid);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" not built: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
					}
					logger.LogError(val);
				}
			}
			if (_mods.Count == 0)
			{
				Plugin.Logger.LogWarning((object)"No BepInEx plugin found.");
				return;
			}
			Select(_mods.FirstOrDefault((ModEntry m) => m.Mod.Guid == _selectedGuid && Listed(m)) ?? _mods.FirstOrDefault(Listed) ?? _mods[0]);
		}

		private static bool Listed(ModEntry m)
		{
			if (!m.HasSettings)
			{
				return !Plugin.HideModsWithoutSettings.Value;
			}
			return true;
		}

		private static void AddModEntry(ModEntry entry)
		{
			GameObject val = Copy(_choiceRow, _modList);
			((Object)val).name = entry.Mod.Guid;
			Transform val2 = val.transform.Find("LabelPanel");
			for (int i = 0; i < val.transform.childCount; i++)
			{
				Transform child = val.transform.GetChild(i);
				if ((Object)(object)child != (Object)(object)val2)
				{
					((Component)child).gameObject.SetActive(false);
				}
			}
			if ((Object)(object)val2 != (Object)null)
			{
				LayoutElement obj = ((Component)val2).GetComponent<LayoutElement>() ?? ((Component)val2).gameObject.AddComponent<LayoutElement>();
				obj.minWidth = 0f;
				obj.preferredWidth = 0f;
				obj.flexibleWidth = 1f;
			}
			HorizontalLayoutGroup component = val.GetComponent<HorizontalLayoutGroup>();
			if ((Object)(object)component != (Object)null)
			{
				((HorizontalOrVerticalLayoutGroup)component).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = true;
			}
			Transform obj2 = val.transform.Find("LabelPanel/Label");
			TMP_Text val3 = ((obj2 != null) ? ((Component)obj2).GetComponent<TMP_Text>() : null);
			if ((Object)(object)val3 == (Object)null)
			{
				throw new InvalidOperationException("row label not found");
			}
			val3.alignment = (TextAlignmentOptions)4097;
			val3.enableWordWrapping = false;
			val3.overflowMode = (TextOverflowModes)1;
			((Graphic)val3).raycastTarget = true;
			((Selectable)(val.GetComponent<Button>() ?? val.AddComponent<Button>())).targetGraphic = (Graphic)(object)val3;
			entry.Go = val;
			entry.Label = val3;
			OnClick(val, delegate
			{
				Select(entry);
			});
			_modTips[((Object)val.transform).GetInstanceID()] = $"{entry.Mod.Name} {entry.Mod.Version}\n{entry.Mod.Guid}";
		}

		private static void Select(ModEntry entry)
		{
			_selectedGuid = entry.Mod.Guid;
			foreach (ModEntry mod in _mods)
			{
				mod.Label.text = ((mod == entry) ? Plugin.SelectedMark.Value : "") + mod.Mod.Name + (Plugin.ShowVersions.Value ? (" " + mod.Mod.Version) : "");
			}
			ShowSettings(entry.Mod);
		}

		private static void ShowSettings(Settings.Mod mod)
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			CancelCapture();
			_resetArmed = false;
			Clear(_settingsList);
			_sections.Clear();
			_rowTips.Clear();
			_shown = mod;
			_shownTip = null;
			SetTip("");
			bool flag = default(bool);
			foreach (IGrouping<string, ConfigEntryBase> item in Settings.Sections(mod.Config))
			{
				Section section = AddSection(item.Key);
				foreach (ConfigEntryBase item2 in item)
				{
					try
					{
						section.Items.Add(AddRow(section, mod.Config, item2));
					}
					catch (Exception ex)
					{
						ManualLogSource logger = Plugin.Logger;
						BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(20, 2, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Row for ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<ConfigDefinition>(item2.Definition);
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" not built: ");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
						}
						logger.LogError(val);
					}
				}
			}
			if (_sections.Count == 0)
			{
				AddSection(Plugin.Text(Plugin.NoSettingsText, "NoSettings"));
			}
			ApplyFilter();
			Plugin.Trace("Showing settings of " + mod.Guid + ".");
		}

		private static Section AddSection(string title)
		{
			GameObject val = Copy(_sectionTemplate, _settingsList);
			Transform val2 = val.transform.Find(_sectionRowsName);
			ClearNow(val2);
			Section section = new Section
			{
				Key = _selectedGuid + "/" + title,
				Title = title,
				Go = val,
				Rows = ((Component)val2).gameObject,
				Label = val.GetComponentInChildren<TMP_Text>(true)
			};
			if ((Object)(object)section.Label != (Object)null)
			{
				section.Label.text = title;
				((Graphic)section.Label).raycastTarget = true;
				Button obj = ((Component)section.Label).GetComponent<Button>() ?? ((Component)section.Label).gameObject.AddComponent<Button>();
				((Selectable)obj).targetGraphic = (Graphic)(object)section.Label;
				OnClick(((Component)obj).gameObject, delegate
				{
					if (section.Items.Count != 0 && _query.Length <= 0)
					{
						_collapsed[section.Key] = !IsFolded(section);
						ApplyFilter();
					}
				});
			}
			_sections.Add(section);
			return section;
		}

		private static bool IsFolded(Section s)
		{
			if (!_collapsed.TryGetValue(s.Key, out var value))
			{
				if (Plugin.CollapseSectionsOver.Value > 0)
				{
					return s.Items.Count > Plugin.CollapseSectionsOver.Value;
				}
				return false;
			}
			return value;
		}

		private static void ApplyFilter()
		{
			bool flag = _query.Length > 0;
			foreach (ModEntry mod in _mods)
			{
				SetShown(mod.Go, Listed(mod) && (!flag || mod.AllText.Contains(_query, StringComparison.Ordinal)));
			}
			if (_shown == null)
			{
				return;
			}
			bool flag2 = flag && _shown.Name.ToLowerInvariant().Contains(_query, StringComparison.Ordinal);
			int num = 0;
			foreach (Section section in _sections)
			{
				int num2 = 0;
				foreach (Row item in section.Items)
				{
					bool flag3 = !flag || flag2 || item.Haystack.Contains(_query, StringComparison.Ordinal);
					SetShown(item.Go, flag3);
					if (flag3)
					{
						num2++;
					}
				}
				SetShown(section.Go, !flag || num2 > 0);
				bool flag4 = flag || !IsFolded(section);
				SetShown(section.Rows, flag4);
				if ((Object)(object)section.Label != (Object)null && section.Items.Count > 0)
				{
					section.Label.text = (flag4 ? Plugin.ExpandedMark.Value : Plugin.CollapsedMark.Value) + section.Title;
				}
				num += num2;
			}
			if (flag && num == 0)
			{
				_shownTip = null;
				SetTip(Plugin.Text(Plugin.NoMatchText, "NoMatch"));
			}
		}

		private static void SetShown(GameObject go, bool shown)
		{
			if ((Object)(object)go != (Object)null && go.activeSelf != shown)
			{
				go.SetActive(shown);
			}
		}

		private static string Haystack(ConfigEntryBase e)
		{
			DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(3, 4);
			defaultInterpolatedStringHandler.AppendFormatted(Names.Readable(e.Definition.Key));
			defaultInterpolatedStringHandler.AppendLiteral("\n");
			defaultInterpolatedStringHandler.AppendFormatted(e.Definition.Key);
			defaultInterpolatedStringHandler.AppendLiteral("\n");
			defaultInterpolatedStringHandler.AppendFormatted(e.Definition.Section);
			defaultInterpolatedStringHandler.AppendLiteral("\n");
			ConfigDescription description = e.Description;
			defaultInterpolatedStringHandler.AppendFormatted((description != null) ? description.Description : null);
			return defaultInterpolatedStringHandler.ToStringAndClear().ToLowerInvariant();
		}

		private static string Tip(ConfigEntryBase e)
		{
			ConfigDescription description = e.Description;
			string text = ((description != null) ? description.Description : null) ?? "";
			string value = TomlTypeConverter.ConvertToString(e.DefaultValue, e.SettingType);
			if (!string.IsNullOrEmpty(value))
			{
				return $"{text}\n{Plugin.Text(Plugin.DefaultText, "Default")}: {value}";
			}
			return text;
		}

		private static Row AddRow(Section section, ConfigFile config, ConfigEntryBase e)
		{
			ControlKind controlKind = Settings.Kind(e);
			object source = controlKind switch
			{
				ControlKind.Slider => _sliderRow, 
				ControlKind.Key => _keyRow ?? _choiceRow, 
				_ => _choiceRow, 
			};
			if (controlKind == ControlKind.Key && (Object)(object)_keyRow == (Object)null)
			{
				controlKind = ControlKind.Text;
			}
			if (controlKind == ControlKind.Text && (Object)(object)_inputField == (Object)null)
			{
				controlKind = ControlKind.Choice;
			}
			GameObject val = Copy((GameObject)source, section.Rows.transform);
			((Object)val).name = e.Definition.Key;
			Row obj = new Row
			{
				Entry = e,
				Config = config,
				Go = val
			};
			Transform obj2 = val.transform.Find("LabelPanel/Label");
			obj.Label = ((obj2 != null) ? ((Component)obj2).GetComponent<TMP_Text>() : null);
			obj.Name = (Plugin.ReadableNames.Value ? Names.Readable(e.Definition.Key) : e.Definition.Key);
			obj.Haystack = Haystack(e);
			Row r = obj;
			_rowTips[((Object)val.transform).GetInstanceID()] = Tip(e);
			Row row = r;
			row.Refresh = controlKind switch
			{
				ControlKind.Slider => SetUpSlider(r), 
				ControlKind.Key => SetUpKey(r), 
				ControlKind.Text => SetUpText(r), 
				_ => SetUpChoice(r, controlKind == ControlKind.Toggle), 
			};
			r.Refresh();
			ShowName(r);
			if ((Object)(object)_defaultButton != (Object)null)
			{
				GameObject obj3 = Copy(_defaultButton, val.transform);
				SetButtonText(obj3, Plugin.Text(Plugin.DefaultText, "Default"));
				OnClick(obj3, delegate
				{
					CancelCapture();
					Settings.ResetToDefault(e);
					r.Refresh();
					Changed(r);
				});
			}
			return r;
		}

		private static void ShowName(Row r)
		{
			if ((Object)(object)r.Label != (Object)null)
			{
				r.Label.text = (Settings.IsDefault(r.Entry) ? "" : Plugin.ModifiedMark.Value) + r.Name;
			}
		}

		private static Action SetUpChoice(Row r, bool isToggle)
		{
			ConfigEntryBase e = r.Entry;
			List<string> values = (isToggle ? null : (Settings.Choices(e) ?? new List<string> { e.GetSerializedValue() }));
			List<string> shown = (isToggle ? new List<string>
			{
				Plugin.Text(Plugin.OffText, "Off"),
				Plugin.Text(Plugin.OnText, "On")
			} : values);
			TMP_Dropdown dropdown = r.Go.GetComponentInChildren<TMP_Dropdown>(true);
			List<string> val = new List<string>();
			foreach (string item2 in shown)
			{
				val.Add(item2);
			}
			dropdown.ClearOptions();
			dropdown.AddOptions(val);
			((UnityEvent<int>)(object)dropdown.onValueChanged).AddListener(UnityAction<int>.op_Implicit((Action<int>)delegate(int i)
			{
				if (isToggle)
				{
					e.BoxedValue = i == 1;
				}
				else if (!Settings.TrySet(e, values[i]))
				{
					SetTip(Plugin.Text(Plugin.InvalidText, "Invalid"));
					return;
				}
				Changed(r);
			}));
			(string, int)[] array = new(string, int)[2]
			{
				("LeftButton", -1),
				("RightButton", 1)
			};
			for (int num = 0; num < array.Length; num++)
			{
				(string, int) tuple = array[num];
				string item = tuple.Item1;
				int delta = tuple.Item2;
				Transform val2 = FindDeep(r.Go.transform, item);
				if ((Object)(object)val2 != (Object)null)
				{
					OnClick(((Component)val2).gameObject, delegate
					{
						dropdown.value = Controls.Step(dropdown.value, delta, shown.Count);
					});
				}
			}
			return delegate
			{
				dropdown.SetValueWithoutNotify(isToggle ? (((bool)e.BoxedValue) ? 1 : 0) : Math.Max(0, values.IndexOf(e.GetSerializedValue())));
			};
		}

		private static Action SetUpSlider(Row r)
		{
			ConfigEntryBase e = r.Entry;
			Settings.Range(e, out var min, out var max);
			bool whole = Settings.IsWholeNumber(e);
			Slider slider = r.Go.GetComponentInChildren<Slider>(true);
			Transform obj = r.Go.transform.Find("SliderPanel/ReadoutLabel");
			TMP_Text readout = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null);
			slider.minValue = (float)min;
			slider.maxValue = (float)max;
			slider.wholeNumbers = whole;
			SonsSlider val = ((Il2CppObjectBase)slider).TryCast<SonsSlider>();
			if ((Object)(object)val != (Object)null)
			{
				val._stepSize = (float)((max - min) / (double)Plugin.SliderSteps.Value);
			}
			((UnityEvent<float>)(object)slider.onValueChanged).AddListener(UnityAction<float>.op_Implicit((Action<float>)delegate(float v)
			{
				Settings.SetNumber(e, whole ? Math.Round(v) : Math.Round(v, Plugin.SliderDecimals.Value));
				if ((Object)(object)readout != (Object)null)
				{
					readout.text = e.GetSerializedValue();
				}
				Changed(r);
			}));
			return delegate
			{
				slider.SetValueWithoutNotify(Convert.ToSingle(e.BoxedValue));
				if ((Object)(object)readout != (Object)null)
				{
					readout.text = e.GetSerializedValue();
				}
			};
		}

		private static Action SetUpKey(Row r)
		{
			foreach (MonoBehaviour component in r.Go.GetComponents<MonoBehaviour>())
			{
				if (((MemberInfo)((Object)component).GetIl2CppType()).Name == "DynamicInputIcon")
				{
					Object.DestroyImmediate((Object)(object)component);
				}
			}
			Transform obj = FindDeep(r.Go.transform, "InputIcon");
			if (obj != null)
			{
				((Component)obj).gameObject.SetActive(false);
			}
			Transform obj2 = FindDeep(r.Go.transform, "WarnIndicator01");
			if (obj2 != null)
			{
				((Component)obj2).gameObject.SetActive(false);
			}
			Button componentInChildren = r.Go.GetComponentInChildren<Button>(true);
			TMP_Text text = ((Component)componentInChildren).GetComponentInChildren<TMP_Text>(true);
			Action result = delegate
			{
				text.text = r.Entry.GetSerializedValue();
			};
			OnClick(((Component)componentInChildren).gameObject, delegate
			{
				if (Time.frameCount - _captureEndFrame > 1)
				{
					CancelCapture();
					_capturing = r.Entry;
					_captureRow = r;
					text.text = Plugin.Text(Plugin.PressKeyText, "PressKey");
				}
			});
			return result;
		}

		private static Action SetUpText(Row r)
		{
			ConfigEntryBase e = r.Entry;
			TMP_InputField field = PutTextField(r.Go);
			Action refresh = delegate
			{
				field.SetTextWithoutNotify(e.GetSerializedValue());
			};
			((UnityEvent<string>)(object)field.onEndEdit).AddListener(UnityAction<string>.op_Implicit((Action<string>)delegate(string s)
			{
				if (!(s == e.GetSerializedValue()))
				{
					if (Settings.TrySet(e, s))
					{
						Changed(r);
					}
					else
					{
						SetTip(Plugin.Text(Plugin.InvalidText, "Invalid"));
					}
					refresh();
				}
			}));
			return refresh;
		}

		private static TMP_InputField PutTextField(GameObject row)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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)
			Transform parent = ((Component)row.GetComponentInChildren<TMP_Dropdown>(true)).transform.parent;
			for (int i = 0; i < parent.childCount; i++)
			{
				if (((Object)parent.GetChild(i)).name != "DropdownBacking")
				{
					((Component)parent.GetChild(i)).gameObject.SetActive(false);
				}
			}
			TMP_InputField component = Copy(_inputField, parent).GetComponent<TMP_InputField>();
			RectTransform component2 = ((Component)component).GetComponent<RectTransform>();
			component2.anchorMin = Vector2.zero;
			component2.anchorMax = Vector2.one;
			component2.offsetMin = Vector2.zero;
			component2.offsetMax = Vector2.zero;
			component.characterLimit = 0;
			component.lineType = (LineType)0;
			Graphic placeholder = component.placeholder;
			TMP_Text val = ((placeholder != null) ? ((Il2CppObjectBase)placeholder).TryCast<TMP_Text>() : null);
			if ((Object)(object)val != (Object)null)
			{
				val.text = "";
			}
			return component;
		}

		private static void ResetAllClicked()
		{
			CancelCapture();
			ConfigFile val = _shown?.Config;
			if (val == null)
			{
				return;
			}
			if (!_resetArmed)
			{
				_resetArmed = true;
				_shownTip = null;
				SetTip(Plugin.Text(Plugin.ConfirmResetAllText, "ConfirmResetAll") + "\n" + _shown.Name);
				return;
			}
			_resetArmed = false;
			int num = 0;
			bool saveOnConfigSet = val.SaveOnConfigSet;
			val.SaveOnConfigSet = false;
			try
			{
				foreach (ConfigEntryBase item in Settings.Entries(val).ToList())
				{
					if (!Settings.IsDefault(item))
					{
						Settings.ResetToDefault(item);
						num++;
					}
				}
			}
			finally
			{
				val.SaveOnConfigSet = saveOnConfigSet;
			}
			val.Save();
			foreach (Section section in _sections)
			{
				foreach (Row item2 in section.Items)
				{
					item2.Refresh();
					ShowName(item2);
				}
			}
			string fileName = Path.GetFileName(val.ConfigFilePath);
			_shownTip = null;
			SetTip($"{Plugin.Text(Plugin.ResetDoneText, "ResetDone")} {num}\n{Plugin.Text(Plugin.SavedText, "Saved")} {fileName}");
			Plugin.Trace($"{num} settings of {_shown.Guid} put back to default ({fileName}).");
		}

		internal static void Tick()
		{
			//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_0045: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown((KeyCode)27))
			{
				if (_capturing != null || Time.frameCount - _captureEndFrame <= 1)
				{
					CancelCapture();
				}
				else
				{
					BackToGame();
				}
			}
			else if (_capturing != null)
			{
				CaptureKey();
			}
			else
			{
				if (_events == null)
				{
					return;
				}
				Vector3 mousePosition = Input.mousePosition;
				bool flag = mousePosition != _lastMouse;
				if (flag)
				{
					_lastMouse = mousePosition;
					TipUnderMouse(mousePosition);
				}
				if (!_gamepad && !flag && !Input.anyKey)
				{
					return;
				}
				GameObject currentSelectedGameObject = _events.currentSelectedGameObject;
				if ((Object)(object)currentSelectedGameObject == (Object)null)
				{
					if (Input.anyKeyDown && !Input.GetMouseButton(0) && !Input.GetMouseButton(1) && !Input.GetMouseButton(2))
					{
						SelectFirstMod();
					}
				}
				else if (!((Object)(object)currentSelectedGameObject == (Object)(object)_lastSelected))
				{
					_lastSelected = currentSelectedGameObject;
					KeepInView(currentSelectedGameObject.transform);
					if (!flag)
					{
						ShowTipOf(currentSelectedGameObject.transform);
					}
				}
			}
		}

		private static void SelectFirstMod()
		{
			foreach (ModEntry mod in _mods)
			{
				if (mod.Go.activeSelf)
				{
					_events.SetSelectedGameObject(mod.Go);
					break;
				}
			}
		}

		private static void KeepInView(Transform selected)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			Transform val = (selected.IsChildOf(_settingsList) ? _settingsList : (selected.IsChildOf(_modList) ? _modList : null));
			RectTransform val2 = ((Il2CppObjectBase)selected).TryCast<RectTransform>();
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				return;
			}
			RectTransform val3 = ((Il2CppObjectBase)val).TryCast<RectTransform>();
			RectTransform obj = ((Il2CppObjectBase)val.parent).TryCast<RectTransform>();
			Rect rect = val3.rect;
			float yMax = ((Rect)(ref rect)).yMax;
			rect = val2.rect;
			float num = yMax - ((Transform)val3).InverseTransformPoint(((Transform)val2).TransformPoint(new Vector3(0f, ((Rect)(ref rect)).yMax, 0f))).y;
			rect = val3.rect;
			float yMax2 = ((Rect)(ref rect)).yMax;
			rect = val2.rect;
			float num2 = yMax2 - ((Transform)val3).InverseTransformPoint(((Transform)val2).TransformPoint(new Vector3(0f, ((Rect)(ref rect)).yMin, 0f))).y;
			float y = val3.anchoredPosition.y;
			rect = obj.rect;
			float height = ((Rect)(ref rect)).height;
			if (num < y)
			{
				y = num;
			}
			else
			{
				if (!(num2 > y + height))
				{
					return;
				}
				y = num2 - height;
			}
			val3.anchoredPosition = new Vector2(val3.anchoredPosition.x, y);
		}

		private unsafe static void CaptureKey()
		{
			//IL_0027: 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_002e: Invalid comparison between Unknown and I4
			//IL_004f: 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)
			if (Input.GetKeyDown((KeyCode)27))
			{
				CancelCapture();
			}
			else
			{
				if (!Input.anyKeyDown)
				{
					return;
				}
				KeyCode[] allKeys = AllKeys;
				for (int i = 0; i < allKeys.Length; i++)
				{
					KeyCode val = allKeys[i];
					if ((int)val != 323 && (!Settings.IsShortcut(_capturing) || !Modifiers.Contains(val)) && Input.GetKeyDown(val))
					{
						IEnumerable<string> modifiers = (Settings.IsShortcut(_capturing) ? (from k in ((IEnumerable<KeyCode>)Modifiers).Where((Func<KeyCode, bool>)Input.GetKey)
							select ((object)(*(KeyCode*)(&k))/*cast due to .constrained prefix*/).ToString()) : null);
						ConfigEntryBase capturing = _capturing;
						Row captureRow = _captureRow;
						_capturing = null;
						_captureEndFrame = Time.frameCount;
						bool num = Settings.TrySet(capturing, Controls.KeyText(((object)(*(KeyCode*)(&val))/*cast due to .constrained prefix*/).ToString(), modifiers));
						captureRow.Refresh();
						if (num)
						{
							Changed(captureRow);
						}
						else
						{
							SetTip(Plugin.Text(Plugin.InvalidText, "Invalid"));
						}
						break;
					}
				}
			}
		}

		private static void CancelCapture()
		{
			if (_capturing != null)
			{
				_capturing = null;
				_captureEndFrame = Time.frameCount;
				_captureRow?.Refresh();
			}
		}

		private static void TipUnderMouse(Vector3 mouse)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (_pointer != null)
			{
				_pointer.position = new Vector2(mouse.x, mouse.y);
				_events.RaycastAll(_pointer, _hits);
				if (_hits.Count > 0)
				{
					ShowTipOf(_hits[0].gameObject.transform);
				}
			}
		}

		private static void ShowTipOf(Transform target)
		{
			Transform val = target;
			while ((Object)(object)val != (Object)null)
			{
				int instanceID = ((Object)val).GetInstanceID();
				if (_rowTips.TryGetValue(instanceID, out var value) || _modTips.TryGetValue(instanceID, out value))
				{
					if (value != _shownTip)
					{
						_shownTip = value;
						SetTip(value);
					}
					break;
				}
				val = val.parent;
			}
		}

		private static void Changed(Row r)
		{
			_resetArmed = false;
			ShowName(r);
			string fileName = Path.GetFileName(r.Config.ConfigFilePath);
			_shownTip = null;
			SetTip($"{r.Name} = {r.Entry.GetSerializedValue()}\n{Plugin.Text(Plugin.SavedText, "Saved")} {fileName}");
			Plugin.Trace($"{r.Entry.Definition} set to '{r.Entry.GetSerializedValue()}' ({fileName}).");
		}

		private static GameObject CopyAsleep(GameObject source, out GameObject holder)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			holder = new GameObject("ModConfigMenu_Holder");
			holder.SetActive(false);
			holder.transform.SetParent(source.transform.parent, false);
			return Object.Instantiate<GameObject>(source, holder.transform);
		}

		private static GameObject Copy(GameObject source, Transform parent)
		{
			GameObject holder;
			GameObject obj = CopyAsleep(source, out holder);
			Strip(obj);
			obj.transform.SetParent(parent, false);
			Object.Destroy((Object)(object)holder);
			obj.SetActive(true);
			return obj;
		}

		private static void Strip(GameObject copy)
		{
			foreach (MonoBehaviour componentsInChild in copy.GetComponentsInChildren<MonoBehaviour>(true))
			{
				if ((Object)(object)componentsInChild != (Object)null && ((Object)(object)((Il2CppObjectBase)componentsInChild).TryCast<OptionsGui>() != (Object)null || GameLogic.Contains(((MemberInfo)((Object)componentsInChild).GetIl2CppType()).Name)))
				{
					Object.DestroyImmediate((Object)(object)componentsInChild);
				}
			}
			Transform transform = copy.transform;
			foreach (Button componentsInChild2 in copy.GetComponentsInChildren<Button>(true))
			{
				CutOutside((UnityEventBase)(object)componentsInChild2.onClick, transform);
			}
			foreach (Toggle componentsInChild3 in copy.GetComponentsInChildren<Toggle>(true))
			{
				CutOutside((UnityEventBase)(object)componentsInChild3.onValueChanged, transform);
			}
			foreach (Slider componentsInChild4 in copy.GetComponentsInChildren<Slider>(true))
			{
				CutOutside((UnityEventBase)(object)componentsInChild4.onValueChanged, transform);
			}
			foreach (Scrollbar componentsInChild5 in copy.GetComponentsInChildren<Scrollbar>(true))
			{
				CutOutside((UnityEventBase)(object)componentsInChild5.onValueChanged, transform);
			}
			foreach (ScrollRect componentsInChild6 in copy.GetComponentsInChildren<ScrollRect>(true))
			{
				CutOutside((UnityEventBase)(object)componentsInChild6.onValueChanged, transform);
			}
			foreach (TMP_Dropdown componentsInChild7 in copy.GetComponentsInChildren<TMP_Dropdown>(true))
			{
				CutOutside((UnityEventBase)(object)componentsInChild7.onValueChanged, transform);
			}
			foreach (TMP_InputField componentsInChild8 in copy.GetComponentsInChildren<TMP_InputField>(true))
			{
				CutOutside((UnityEventBase)(object)componentsInChild8.onValueChanged, transform);
				CutOutside((UnityEventBase)(object)componentsInChild8.onEndEdit, transform);
				CutOutside((UnityEventBase)(object)componentsInChild8.onSubmit, transform);
				CutOutside((UnityEventBase)(object)componentsInChild8.onSelect, transform);
				CutOutside((UnityEventBase)(object)componentsInChild8.onDeselect, transform);
			}
			foreach (EventTrigger componentsInChild9 in copy.GetComponentsInChildren<EventTrigger>(true))
			{
				Enumerator<Entry> enumerator10 = componentsInChild9.triggers.GetEnumerator();
				while (enumerator10.MoveNext())
				{
					CutOutside((UnityEventBase)(object)enumerator10.Current.callback, transform);
				}
			}
		}

		private static void CutOutside(UnityEventBase ev, Transform root)
		{
			if (ev == null)
			{
				return;
			}
			for (int i = 0; i < ev.GetPersistentEventCount(); i++)
			{
				Object persistentTarget = ev.GetPersistentTarget(i);
				Transform val = null;
				if (persistentTarget != (Object)null)
				{
					Component obj = ((Il2CppObjectBase)persistentTarget).TryCast<Component>();
					object obj2 = ((obj != null) ? obj.transform : null);
					if (obj2 == null)
					{
						GameObject obj3 = ((Il2CppObjectBase)persistentTarget).TryCast<GameObject>();
						obj2 = ((obj3 != null) ? obj3.transform : null);
					}
					val = (Transform)obj2;
				}
				if ((Object)(object)val == (Object)null || !val.IsChildOf(root))
				{
					ev.SetPersistentListenerState(i, (UnityEventCallState)0);
				}
			}
		}

		private static void OnClick(GameObject go, Action action)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			Button component = go.GetComponent<Button>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			component.onClick = new ButtonClickedEvent();
			((UnityEvent)component.onClick).AddListener(UnityAction.op_Implicit((Action)delegate
			{
				action();
				if ((Object)(object)_events != (Object)null && (Input.GetMouseButtonUp(0) || Input.GetMouseButton(0)))
				{
					_events.SetSelectedGameObject((GameObject)null);
				}
			}));
		}

		private static Transform FindDeep(Transform root, string name)
		{
			foreach (Transform componentsInChild in ((Component)root).GetComponentsInChildren<Transform>(true))
			{
				if (((Object)componentsInChild).name == name)
				{
					return componentsInChild;
				}
			}
			return null;
		}

		private static void Clear(Transform t)
		{
			for (int num = t.childCount - 1; num >= 0; num--)
			{
				GameObject gameObject = ((Component)t.GetChild(num)).gameObject;
				gameObject.SetActive(false);
				gameObject.transform.SetParent((Transform)null, false);
				Object.Destroy((Object)(object)gameObject);
			}
		}

		private static void ClearNow(Transform t)
		{
			for (int num = t.childCount - 1; num >= 0; num--)
			{
				Object.DestroyImmediate((Object)(object)((Component)t.GetChild(num)).gameObject);
			}
		}

		private static string GameText(Transform button)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			if ((Object)(object)button == (Object)null)
			{
				return null;
			}
			try
			{
				LinkTextGui component = ((Component)button).GetComponent<LinkTextGui>();
				return (component != null) ? component.GetText() : null;
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(26, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Game text of '");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)button).name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' not read: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				}
				logger.LogWarning(val);
				return null;
			}
		}

		internal static void SetButtonText(GameObject button, string text)
		{
			if (!((Object)(object)button == (Object)null))
			{
				LinkTextGui component = button.GetComponent<LinkTextGui>();
				if ((Object)(object)component != (Object)null)
				{
					component.SetText(text);
				}
				TMP_Text componentInChildren = button.GetComponentInChildren<TMP_Text>(true);
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.text = text;
				}
			}
		}

		private static void SetTip(string text)
		{
			if ((Object)(object)_tip != (Object)null)
			{
				_tip.text = text;
			}
		}

		private static Color WithAlpha(Color c, float a)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			c.a = a;
			return c;
		}

		private static int Recolor(GameObject tab, Color from, Color to)
		{
			//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_001f: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			foreach (Graphic componentsInChild in tab.GetComponentsInChildren<Graphic>(true))
			{
				Color color = componentsInChild.color;
				if (!(Mathf.Abs(color.r - from.r) + Mathf.Abs(color.g - from.g) + Mathf.Abs(color.b - from.b) > 0.02f))
				{
					componentsInChild.color = new Color(to.r, to.g, to.b, color.a);
					num++;
				}
			}
			return num;
		}

		private static void LogLayout()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0355: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			Canvas.ForceUpdateCanvases();
			Rect rect = ((Il2CppObjectBase)((Transform)_modColumn).parent).TryCast<RectTransform>().rect;
			float width = ((Rect)(ref rect)).width;
			rect = _modColumn.rect;
			float width2 = ((Rect)(ref rect)).width;
			rect = _settingsColumn.rect;
			float width3 = ((Rect)(ref rect)).width;
			ModEntry modEntry = _mods.FirstOrDefault((ModEntry m) => m.Go.activeSelf);
			Section section = _sections.FirstOrDefault((Section s) => s.Go.activeSelf);
			DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(165, 17);
			defaultInterpolatedStringHandler.AppendLiteral("Layout: page ");
			rect = _page.GetComponent<RectTransform>().rect;
			defaultInterpolatedStringHandler.AppendFormatted<Vector2>(((Rect)(ref rect)).size);
			defaultInterpolatedStringHandler.AppendLiteral(", body width ");
			defaultInterpolatedStringHandler.AppendFormatted(width);
			defaultInterpolatedStringHandler.AppendLiteral(", mod list ");
			rect = _modColumn.rect;
			defaultInterpolatedStringHandler.AppendFormatted<Vector2>(((Rect)(ref rect)).size);
			defaultInterpolatedStringHandler.AppendLiteral(" at x ");
			defaultInterpolatedStringHandler.AppendFormatted(_modColumn.anchorMin.x);
			defaultInterpolatedStringHandler.AppendLiteral("-");
			defaultInterpolatedStringHandler.AppendFormatted(_modColumn.anchorMax.x);
			defaultInterpolatedStringHandler.AppendLiteral(", ");
			defaultInterpolatedStringHandler.AppendLiteral("settings ");
			rect = _settingsColumn.rect;
			defaultInterpolatedStringHandler.AppendFormatted<Vector2>(((Rect)(ref rect)).size);
			defaultInterpolatedStringHandler.AppendLiteral(" at x ");
			defaultInterpolatedStringHandler.AppendFormatted(_settingsColumn.anchorMin.x);
			defaultInterpolatedStringHandler.AppendLiteral("-");
			defaultInterpolatedStringHandler.AppendFormatted(_settingsColumn.anchorMax.x);
			defaultInterpolatedStringHandler.AppendLiteral(", search bar ");
			rect = _searchBar.rect;
			defaultInterpolatedStringHandler.AppendFormatted<Vector2>(((Rect)(ref rect)).size);
			defaultInterpolatedStringHandler.AppendLiteral(", ");
			defaultInterpolatedStringHandler.AppendLiteral("columns overlap: ");
			defaultInterpolatedStringHandler.AppendFormatted((width2 + width3 > width + 1f) ? "YES" : "no");
			defaultInterpolatedStringHandler.AppendLiteral(", ");
			defaultInterpolatedStringHandler.AppendLiteral("first mod entry ");
			Vector2? value;
			if (modEntry == null)
			{
				value = null;
			}
			else
			{
				rect = modEntry.Go.GetComponent<RectTransform>().rect;
				value = ((Rect)(ref rect)).size;
			}
			defaultInterpolatedStringHandler.AppendFormatted(value);
			defaultInterpolatedStringHandler.AppendLiteral(" text '");
			defaultInterpolatedStringHandler.AppendFormatted((modEntry != null) ? modEntry.Label.text : null);
			defaultInterpolatedStringHandler.AppendLiteral("' aligned ");
			defaultInterpolatedStringHandler.AppendFormatted((modEntry != null) ? new TextAlignmentOptions?(modEntry.Label.alignment) : ((TextAlignmentOptions?)null));
			defaultInterpolatedStringHandler.AppendLiteral(" size ");
			defaultInterpolatedStringHandler.AppendFormatted((modEntry != null) ? new float?(modEntry.Label.fontSize) : ((float?)null));
			defaultInterpolatedStringHandler.AppendLiteral(", ");
			defaultInterpolatedStringHandler.AppendLiteral("first section '");
			defaultInterpolatedStringHandler.AppendFormatted(section?.Title);
			defaultInterpolatedStringHandler.AppendLiteral("' ");
			Vector2? value2;
			if (section == null)
			{
				value2 = null;
			}
			else
			{
				rect = section.Go.GetComponent<RectTransform>().rect;
				value2 = ((Rect)(ref rect)).size;
			}
			defaultInterpolatedStringHandler.AppendFormatted(value2);
			defaultInterpolatedStringHandler.AppendLiteral(", sections ");
			defaultInterpolatedStringHandler.AppendFormatted(string.Join(" | ", _sections.Select((Section s) => s.Title)));
			Plugin.Trace(defaultInterpolatedStringHandler.ToStringAndClear());
		}
	}
	public class PageDriver : MonoBehaviour
	{
		public PageDriver(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Update()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			try
			{
				ModsPage.Tick();
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(25, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Mods page update failed: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val);
				((Behaviour)this).enabled = false;
			}
		}
	}
	[HarmonyPatch(typeof(OptionsGuiManager), "OnEnable")]
	public static class OptionsTabInjector
	{
		public static void Postfix(OptionsGuiManager __instance)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			try
			{
				ModsPage.AddTab(__instance);
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(20, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Mods tab not added: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val);
			}
		}
	}
	[HarmonyPatch(typeof(PauseMenu), "OnBack")]
	public static class BackKeyPatch
	{
		public static bool Prefix()
		{
			return !ModsPage.OwnsBack();
		}
	}
	[HarmonyPatch(typeof(PauseMenu), "Close")]
	public static class ClosePatch
	{
		public static void Prefix()
		{
			ModsPage.Close();
		}
	}
}
namespace ModConfigMenu.Logic
{
	public enum ControlKind
	{
		Toggle,
		Choice,
		Slider,
		Key,
		Text
	}
	public static class Controls
	{
		public static ControlKind Pick(bool isBool, bool isKey, bool hasChoices, bool hasRange)
		{
			if (!isBool)
			{
				if (!isKey)
				{
					if (!hasChoices)
					{
						if (!hasRange)
						{
							return ControlKind.Text;
						}
						return ControlKind.Slider;
					}
					return ControlKind.Choice;
				}
				return ControlKind.Key;
			}
			return ControlKind.Toggle;
		}

		public static string KeyText(string mainKey, IEnumerable<string> modifiers)
		{
			return string.Join(" + ", new string[1] { mainKey }.Concat(modifiers ?? Enumerable.Empty<string>()));
		}

		public static int Step(int index, int delta, int count)
		{
			if (count > 0)
			{
				return ((index + delta) % count + count) % count;
			}
			return 0;
		}

		public static void SelfCheck()
		{
			if (Pick(isBool: true, isKey: false, hasChoices: true, hasRange: true) != ControlKind.Toggle || Pick(isBool: false, isKey: true, hasChoices: false, hasRange: false) != ControlKind.Key || Pick(isBool: false, isKey: false, hasChoices: true, hasRange: true) != ControlKind.Choice || Pick(isBool: false, isKey: false, hasChoices: false, hasRange: true) != ControlKind.Slider || Pick(isBool: false, isKey: false, hasChoices: false, hasRange: false) != ControlKind.Text)
			{
				throw new InvalidOperationException("Controls.Pick is wrong.");
			}
			if (KeyText("F8", new string[1] { "LeftControl" }) != "F8 + LeftControl" || KeyText("F8", null) != "F8")
			{
				throw new InvalidOperationException("Controls.KeyText is wrong.");
			}
			if (Step(0, -1, 3) != 2 || Step(2, 1, 3) != 0 || Step(1, 1, 3) != 2 || Step(0, 1, 0) != 0)
			{
				throw new InvalidOperationException("Controls.Step is wrong.");
			}
		}
	}
	public static class Names
	{
		public static string Readable(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				return key ?? "";
			}
			List<string> words = new List<string>();
			StringBuilder word = new StringBuilder();
			for (int i = 0; i < key.Length; i++)
			{
				char c = key[i];
				if (c == '_' || c == ' ' || c == '-')
				{
					Flush();
					continue;
				}
				if (char.IsUpper(c) && word.Length > 0 && (!char.IsUpper(key[i - 1]) || (i + 1 < key.Length && char.IsLower(key[i + 1]))))
				{
					Flush();
				}
				word.Append(c);
			}
			Flush();
			string text = string.Join(" ", words.Select((string w) => (w.Length <= 1 || !w.All((char ch) => !char.IsLower(ch))) ? w.ToLowerInvariant() : w));
			if (text.Length != 0)
			{
				return char.ToUpperInvariant(text[0]) + text.Substring(1);
			}
			return text;
			void Flush()
			{
				if (word.Length > 0)
				{
					words.Add(word.ToString());
					word.Clear();
				}
			}
		}

		public static List<string> SectionOrder(IEnumerable<string> declared, string first, string last = "")
		{
			List<string> all = declared.ToList();
			List<string> top = Named(first);
			List<string> bottom = (from d in Named(last)
				where !top.Contains(d)
				select d).ToList();
			return top.Concat(all.Where((string d) => !top.Contains(d) && !bottom.Contains(d))).Concat(bottom).ToList();
			List<string> Named(string list)
			{
				return (from s in (list ?? "").Split(',')
					select s.Trim() into s
					where s.Length > 0
					select all.FirstOrDefault((string d) => string.Equals(d, s, StringComparison.OrdinalIgnoreCase)) into s
					where s != null
					select s).Distinct().ToList();
			}
		}

		public static void SelfCheck()
		{
			if (Readable("EnemiesFrozen") != "Enemies frozen" || Readable("AIEnabled") != "AI enabled" || Readable("Slug_Deprecated") != "Slug deprecated" || Readable("F8Key") != "F8 key" || Readable("Robby") != "Robby" || Readable("") != "")
			{
				throw new InvalidOperationException("Names.Readable is wrong.");
			}
			if (string.Join("|", SectionOrder(new string[3] { "Frozen types", "General", "Message" }, "general, Missing")) != "General|Frozen types|Message" || string.Join("|", SectionOrder(new string[2] { "B", "A" }, "")) != "B|A" || string.Join("|", SectionOrder(new string[4] { "Debug", "Texts", "General", "Camera" }, "General", "Texts, Performance, Debug")) != "General|Camera|Texts|Debug")
			{
				throw new InvalidOperationException("Names.SectionOrder is wrong.");
			}
		}
	}
	public static class Texts
	{
		public const string Mods = "Mods";

		public const string Default = "Default";

		public const string PressKey = "PressKey";

		public const string On = "On";

		public const string Off = "Off";

		public const string NoSettings = "NoSettings";

		public const string Saved = "Saved";

		public const string Invalid = "Invalid";

		public const string Search = "Search";

		public const string NoMatch = "NoMatch";

		public const string ResetAll = "ResetAll";

		public const string ConfirmResetAll = "ConfirmResetAll";

		public const string ResetDone = "ResetDone";

		private static readonly Dictionary<string, Dictionary<string, string>> ByLanguage = new Dictionary<string, Dictionary<string, string>>
		{
			["en"] = new Dictionary<string, string>
			{
				["Mods"] = "Mods",
				["Default"] = "Default",
				["PressKey"] = "Press a key...",
				["On"] = "On",
				["Off"] = "Off",
				["NoSettings"] = "This mod has no settings",
				["Saved"] = "Saved to",
				["Invalid"] = "Value refused, kept",
				["Search"] = "Search",
				["NoMatch"] = "No setting matches the search",
				["ResetAll"] = "Reset all",
				["ConfirmResetAll"] = "Click again to put every setting of this mod back to its default value:",
				["ResetDone"] = "Settings put back to default:"
			},
			["fr"] = new Dictionary<string, string>
			{
				["Mods"] = "Mods",
				["Default"] = "Défaut",
				["PressKey"] = "Appuyez sur une touche...",
				["On"] = "Activé",
				["Off"] = "Désactivé",
				["NoSettings"] = "Ce mod n'a aucun réglage",
				["Saved"] = "Enregistré dans",
				["Invalid"] = "Valeur refusée, conservé",
				["Search"] = "Rechercher",
				["NoMatch"] = "Aucun réglage ne correspond à la recherche",
				["ResetAll"] = "Tout par défaut",
				["ConfirmResetAll"] = "Cliquez encore pour remettre tous les réglages de ce mod à leur valeur par défaut :",
				["ResetDone"] = "Réglages remis par défaut :"
			}
		};

		public static string Get(string localeCode, string key)
		{
			string key2 = (localeCode ?? "en").Split('-')[0].ToLowerInvariant();
			if (!ByLanguage.TryGetValue(key2, out var value) || !value.TryGetValue(key, out var value2))
			{
				return ByLanguage["en"][key];
			}
			return value2;
		}

		public static void SelfCheck()
		{
			foreach (string key in ByLanguage["fr"].Keys)
			{
				if (!ByLanguage["en"].ContainsKey(key))
				{
					throw new InvalidOperationException("Texts: '" + key + "' missing in English.");
				}
			}
			if (Get("fr-FR", "Default") != "Défaut" || Get("ja", "Default") != "Default" || Get(null, "On") != "On")
			{
				throw new InvalidOperationException("Texts lookup is wrong.");
			}
		}
	}
}