Decompiled source of Nivalis Mod Settings v1.0.1

NivalisSettings.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
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 Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Reflection;
using Microsoft.CodeAnalysis;
using Nivalis;
using Nivalis.Localization;
using Nivalis.UI.Concrete;
using Nivalis.UI.InGameMenu;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
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("NivalisSettings")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("NivalisSettings")]
[assembly: AssemblyTitle("NivalisSettings")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace NivalisSettings
{
	internal static class MenuPatches
	{
		[HarmonyPatch(typeof(SettingsPanel), "Show")]
		[HarmonyPrefix]
		private static void SettingsShow(SettingsPanel __instance)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			try
			{
				ModsTab.GetOrCreate(__instance);
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(28, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not add the Mods tab: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val);
			}
		}

		[HarmonyPatch(typeof(SettingsPanel), "TabSelected")]
		[HarmonyPrefix]
		private static bool SettingsTabSelected(SettingsPanel __instance)
		{
			return !ModsTab.IsShowingMods(__instance);
		}

		[HarmonyPatch(typeof(MainMenuUI), "Start")]
		[HarmonyPostfix]
		private static void MainMenuStart(MainMenuUI __instance)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			if (!Plugin.MenuButton.Value)
			{
				return;
			}
			try
			{
				AddMenuButton(__instance);
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(36, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not add the Mods menu button: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val);
			}
		}

		private static void AddMenuButton(MainMenuUI menu)
		{
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			Button settingsButton = menu.settingsButton;
			if ((Object)(object)settingsButton == (Object)null)
			{
				return;
			}
			Transform parent = ((Component)settingsButton).transform.parent;
			if ((Object)(object)((Component)parent).GetComponent<LayoutGroup>() == (Object)null)
			{
				Plugin.Logger.LogWarning((object)"Main menu buttons have no layout group, skipping the Mods button");
				return;
			}
			GameObject val = Object.Instantiate<GameObject>(((Component)settingsButton).gameObject, parent);
			((Object)val).name = "NivalisModsButton";
			val.transform.SetSiblingIndex(((Component)settingsButton).transform.GetSiblingIndex() + 1);
			UiUtil.StripLocalization(val);
			foreach (TextMeshProUGUI componentsInChild in val.GetComponentsInChildren<TextMeshProUGUI>(true))
			{
				((TMP_Text)componentsInChild).text = "Mods";
			}
			Button component = val.GetComponent<Button>();
			component.onClick = new ButtonClickedEvent();
			((UnityEvent)component.onClick).AddListener(UnityAction.op_Implicit((Action)delegate
			{
				menu.OpenSettingsPanel();
				ModsDriver.RequestModsTab(menu.settingsPanel);
			}));
		}
	}
	public class ModsDriver : MonoBehaviour
	{
		private static SettingsPanel _pending;

		private static int _pendingFrames;

		public ModsDriver(IntPtr ptr)
			: base(ptr)
		{
		}

		public static void RequestModsTab(SettingsPanel panel)
		{
			_pending = panel;
			_pendingFrames = 2;
		}

		private void Update()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			bool flag = default(bool);
			if ((Object)(object)_pending != (Object)null && --_pendingFrames <= 0)
			{
				SettingsPanel pending = _pending;
				_pending = null;
				try
				{
					ModsTab.GetOrCreate(pending)?.ShowMods();
				}
				catch (Exception ex)
				{
					ManualLogSource logger = Plugin.Logger;
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(29, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not open the Mods tab: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
					}
					logger.LogError(val);
				}
			}
			foreach (ModsTab item in ModsTab.All.ToList())
			{
				try
				{
					item.Tick();
				}
				catch (Exception ex2)
				{
					ManualLogSource logger2 = Plugin.Logger;
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(24, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Mods tab update failed: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex2);
					}
					logger2.LogError(val);
					ModsTab.Remove(item);
				}
			}
		}

		private void OnApplicationQuit()
		{
			ModsTab.SaveAll();
		}
	}
	public static class ModSettings
	{
		public const string Guid = "com.asher.nivalissettings";

		private static readonly List<ModPage> _pages = new List<ModPage>();

		private static readonly Dictionary<string, ModPage> _autoPages = new Dictionary<string, ModPage>();

		internal static int Version { get; private set; }

		public static IReadOnlyList<ModPage> RegisteredPages => _pages;

		public static ModPage Register(BasePlugin plugin, string displayName = null)
		{
			if (plugin == null)
			{
				throw new ArgumentNullException("plugin");
			}
			BepInPlugin metadata = MetadataHelper.GetMetadata((object)plugin);
			return Register(metadata.GUID, displayName ?? metadata.Name, plugin.Config);
		}

		public static ModPage Register(string id, string displayName, ConfigFile config)
		{
			if (string.IsNullOrEmpty(id))
			{
				throw new ArgumentException("id is required", "id");
			}
			if (config == null)
			{
				throw new ArgumentNullException("config");
			}
			ModPage modPage = _pages.FirstOrDefault((ModPage p) => p.Id == id);
			if (modPage != null)
			{
				return modPage;
			}
			modPage = new ModPage(id, displayName ?? id, config);
			_pages.Add(modPage);
			Changed();
			return modPage;
		}

		public static void Unregister(string id)
		{
			if (_pages.RemoveAll((ModPage p) => p.Id == id) > 0)
			{
				Changed();
			}
		}

		internal static void Changed()
		{
			Version++;
		}

		internal static List<ModPage> VisiblePages()
		{
			List<ModPage> list = new List<ModPage>(_pages);
			if (Plugin.ShowAllPlugins.Value)
			{
				foreach (PluginInfo value2 in ((BaseChainloader<BasePlugin>)(object)IL2CPPChainloader.Instance).Plugins.Values)
				{
					object instance = value2.Instance;
					BasePlugin val = (BasePlugin)((instance is BasePlugin) ? instance : null);
					if (val == null || val.Config.Count == 0)
					{
						continue;
					}
					string id = value2.Metadata.GUID;
					if (!(id == "com.asher.nivalissettings") && !_pages.Any((ModPage p) => p.Id == id))
					{
						if (!_autoPages.TryGetValue(id, out var value))
						{
							value = (_autoPages[id] = new ModPage(id, value2.Metadata.Name, val.Config));
						}
						list.Add(value);
					}
				}
			}
			return (from p in list
				orderby (p.Id == "com.asher.nivalissettings") ? 1 : 0, p.Order, p.DisplayName
				select p).ToList();
		}
	}
	public sealed class ModPage
	{
		internal readonly struct Item
		{
			public readonly ConfigEntryBase Entry;

			public readonly string ButtonLabel;

			public readonly Action ButtonAction;

			public Item(ConfigEntryBase entry)
			{
				Entry = entry;
				ButtonLabel = null;
				ButtonAction = null;
			}

			public Item(string label, Action action)
			{
				Entry = null;
				ButtonLabel = label;
				ButtonAction = action;
			}
		}

		private readonly HashSet<ConfigEntryBase> _hidden = new HashSet<ConfigEntryBase>();

		private readonly HashSet<string> _hiddenSections = new HashSet<string>();

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

		private readonly Dictionary<string, string> _sectionLabels = new Dictionary<string, string>();

		private readonly List<(string Section, string Label, Action Action)> _buttons = new List<(string, string, Action)>();

		private string _displayName;

		private int _order;

		public string Id { get; }

		public ConfigFile Config { get; }

		public string DisplayName
		{
			get
			{
				return _displayName;
			}
			set
			{
				_displayName = value;
				ModSettings.Changed();
			}
		}

		public int Order
		{
			get
			{
				return _order;
			}
			set
			{
				_order = value;
				ModSettings.Changed();
			}
		}

		internal ModPage(string id, string displayName, ConfigFile config)
		{
			Id = id;
			_displayName = displayName;
			Config = config;
		}

		public ModPage Hide(ConfigEntryBase entry)
		{
			_hidden.Add(entry);
			ModSettings.Changed();
			return this;
		}

		public ModPage HideSection(string section)
		{
			_hiddenSections.Add(section);
			ModSettings.Changed();
			return this;
		}

		public ModPage Label(ConfigEntryBase entry, string label)
		{
			_labels[entry] = label;
			ModSettings.Changed();
			return this;
		}

		public ModPage SectionLabel(string section, string label)
		{
			_sectionLabels[section] = label;
			ModSettings.Changed();
			return this;
		}

		public ModPage Button(string section, string label, Action onClick)
		{
			_buttons.Add((section, label, onClick));
			ModSettings.Changed();
			return this;
		}

		internal string GetLabel(ConfigEntryBase entry)
		{
			if (!_labels.TryGetValue(entry, out var value))
			{
				return Nicify(entry.Definition.Key);
			}
			return value;
		}

		internal string GetSectionLabel(string section)
		{
			if (!_sectionLabels.TryGetValue(section, out var value))
			{
				return section;
			}
			return value;
		}

		internal List<(string Section, List<Item> Items)> Layout()
		{
			List<(string Section, List<Item> Items)> sections = new List<(string, List<Item>)>();
			foreach (ConfigEntryBase value in Config.Values)
			{
				if (!_hidden.Contains(value) && !_hiddenSections.Contains(value.Definition.Section))
				{
					Get(value.Definition.Section).Add(new Item(value));
				}
			}
			foreach (var (name, label, action) in _buttons)
			{
				Get(name).Add(new Item(label, action));
			}
			return sections.OrderBy(((string Section, List<Item> Items) s) => (s.Section == "Debug") ? 1 : 0).ToList();
			List<Item> Get(string text)
			{
				foreach (var item in sections)
				{
					if (item.Section == text)
					{
						return item.Items;
					}
				}
				List<Item> list = new List<Item>();
				sections.Add((text, list));
				return list;
			}
		}

		internal IEnumerable<ConfigEntryBase> VisibleEntries()
		{
			return from i in Layout().SelectMany(((string Section, List<Item> Items) s) => s.Items)
				where i.Entry != null
				select i.Entry;
		}

		internal static string Nicify(string key)
		{
			StringBuilder stringBuilder = new StringBuilder(key.Length + 4);
			for (int i = 0; i < key.Length; i++)
			{
				char c = key[i];
				if (i > 0 && char.IsUpper(c) && !char.IsUpper(key[i - 1]))
				{
					stringBuilder.Append(' ');
				}
				stringBuilder.Append(c);
			}
			return stringBuilder.ToString();
		}
	}
	internal sealed class ModsTab
	{
		private sealed class Template
		{
			public GameObject Go;

			public string LabelPath;

			public string ValuePath;
		}

		private static readonly List<ModsTab> _tabs = new List<ModsTab>();

		private SettingsPanel _settings;

		private WindowToggleController _controller;

		private UISubPanel _panel;

		private Toggle _tabToggle;

		private GameObject _templates;

		private RectTransform _content;

		private ScrollRect _scroll;

		private Template _slider;

		private Template _toggle;

		private Template _choice;

		private TextMeshProUGUI _headerStyle;

		private float _rowHeight;

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

		private readonly HashSet<ConfigFile> _configs = new HashSet<ConfigFile>();

		private int _builtVersion = -1;

		private bool _visible;

		private int _relayoutFrames;

		private ConfigEntryBase _rebinding;

		private Action _rebindRefresh;

		private static Key[] _keys;

		public static IReadOnlyList<ModsTab> All => _tabs;

		private bool Alive
		{
			get
			{
				if ((Object)(object)_settings != (Object)null)
				{
					return (Object)(object)_panel != (Object)null;
				}
				return false;
			}
		}

		private bool ModsShown
		{
			get
			{
				UISubPanel shownPanel = _controller.ShownPanel;
				if ((Object)(object)shownPanel != (Object)null)
				{
					return ((Il2CppObjectBase)shownPanel).Pointer == ((Il2CppObjectBase)_panel).Pointer;
				}
				return false;
			}
		}

		public static ModsTab GetOrCreate(SettingsPanel settings)
		{
			_tabs.RemoveAll((ModsTab t) => !t.Alive);
			foreach (ModsTab tab in _tabs)
			{
				if (((Il2CppObjectBase)tab._settings).Pointer == ((Il2CppObjectBase)settings).Pointer)
				{
					return tab;
				}
			}
			ModsTab modsTab = new ModsTab();
			if (!modsTab.Create(settings))
			{
				return null;
			}
			_tabs.Add(modsTab);
			return modsTab;
		}

		public static void Remove(ModsTab tab)
		{
			_tabs.Remove(tab);
		}

		public static bool IsShowingMods(SettingsPanel settings)
		{
			foreach (ModsTab tab in _tabs)
			{
				if (tab.Alive && ((Il2CppObjectBase)tab._settings).Pointer == ((Il2CppObjectBase)settings).Pointer)
				{
					return tab.ModsShown;
				}
			}
			return false;
		}

		public static void SaveAll()
		{
			foreach (ModsTab tab in _tabs)
			{
				if (tab._visible)
				{
					tab.OnHidden();
				}
			}
		}

		public void ShowMods()
		{
			if (!_tabToggle.isOn)
			{
				_tabToggle.isOn = true;
			}
			else if (!ModsShown)
			{
				_controller.SwitchToPanel(_panel);
			}
		}

		public void Tick()
		{
			if (!Alive)
			{
				_tabs.Remove(this);
				return;
			}
			bool flag = ((UIPanel)_settings).IsVisible && ModsShown;
			if (flag && !_visible)
			{
				OnShown();
			}
			else if (!flag && _visible)
			{
				OnHidden();
			}
			_visible = flag;
			if (flag)
			{
				if (_builtVersion != ModSettings.Version)
				{
					BuildRows();
					Refresh();
					BeginEditing();
					Relayout();
					_relayoutFrames = 2;
				}
				if (_relayoutFrames > 0 && --_relayoutFrames == 0)
				{
					Relayout();
				}
				if (_rebinding != null)
				{
					CaptureRebind();
				}
			}
		}

		private void Relayout()
		{
			foreach (LayoutGroup componentsInChild in ((Component)_panel).GetComponentsInChildren<LayoutGroup>(true))
			{
				((Behaviour)componentsInChild).enabled = true;
			}
			foreach (ContentSizeFitter componentsInChild2 in ((Component)_panel).GetComponentsInChildren<ContentSizeFitter>(true))
			{
				((Behaviour)componentsInChild2).enabled = true;
			}
			foreach (LayoutElement componentsInChild3 in ((Component)_panel).GetComponentsInChildren<LayoutElement>(true))
			{
				((Behaviour)componentsInChild3).enabled = true;
			}
			foreach (ScrollRect componentsInChild4 in ((Component)_panel).GetComponentsInChildren<ScrollRect>(true))
			{
				((Behaviour)componentsInChild4).enabled = true;
			}
			foreach (Selectable componentsInChild5 in ((Component)_panel).GetComponentsInChildren<Selectable>(true))
			{
				((Behaviour)componentsInChild5).enabled = true;
			}
			VerticalLayoutGroup component = ((Component)_content).GetComponent<VerticalLayoutGroup>();
			if ((Object)(object)component != (Object)null)
			{
				((HorizontalOrVerticalLayoutGroup)component).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = true;
				((HorizontalOrVerticalLayoutGroup)component).childControlHeight = true;
				((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = false;
			}
			LayoutRebuilder.ForceRebuildLayoutImmediate(_content);
			LayoutRebuilder.ForceRebuildLayoutImmediate(((Component)_panel).GetComponent<RectTransform>());
		}

		private void OnShown()
		{
			if (_builtVersion != ModSettings.Version)
			{
				BuildRows();
			}
			Refresh();
			BeginEditing();
			Relayout();
			_relayoutFrames = 2;
			if (Plugin.DumpUi.Value)
			{
				StringBuilder stringBuilder = new StringBuilder("Mods tab hierarchy:\n");
				UiUtil.Dump(((Component)_panel).transform, stringBuilder);
				Plugin.Logger.LogInfo((object)stringBuilder.ToString());
			}
		}

		private void BeginEditing()
		{
			foreach (ConfigFile config in _configs)
			{
				config.SaveOnConfigSet = false;
			}
		}

		private void OnHidden()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			_rebinding = null;
			bool flag = default(bool);
			foreach (ConfigFile config in _configs)
			{
				try
				{
					config.Save();
				}
				catch (Exception ex)
				{
					ManualLogSource logger = Plugin.Logger;
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(17, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not save ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(config.ConfigFilePath);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
					}
					logger.LogError(val);
				}
				config.SaveOnConfigSet = true;
			}
		}

		private void Refresh()
		{
			foreach (Action refresher in _refreshers)
			{
				refresher();
			}
		}

		private bool Create(SettingsPanel settings)
		{
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Expected O, but got Unknown
			_settings = settings;
			_controller = settings.togglesGroup ?? ((Component)settings).GetComponentInChildren<WindowToggleController>(true);
			if ((Object)(object)_controller == (Object)null || _controller.toggles == null || _controller.panels == null || ((Il2CppArrayBase<Toggle>)(object)_controller.toggles).Length == 0)
			{
				Plugin.Logger.LogWarning((object)"Settings window has no tab controller, Mods tab not added");
				return false;
			}
			if (Plugin.DumpUi.Value)
			{
				StringBuilder stringBuilder = new StringBuilder("Settings window hierarchy:\n");
				UiUtil.Dump(((Component)settings).transform, stringBuilder);
				Plugin.Logger.LogInfo((object)stringBuilder.ToString());
			}
			GameplaySettingsUI val = null;
			foreach (UISubPanel item in (Il2CppArrayBase<UISubPanel>)(object)_controller.panels)
			{
				val = ((item != null) ? ((Il2CppObjectBase)item).TryCast<GameplaySettingsUI>() : null);
				if ((Object)(object)val != (Object)null)
				{
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Logger.LogWarning((object)"Gameplay settings tab not found, Mods tab not added");
				return false;
			}
			_templates = new GameObject("NivalisModsTemplates");
			_templates.SetActive(false);
			_templates.transform.SetParent(((Component)settings).transform, false);
			GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, _templates.transform);
			((Object)val2).name = "NivalisModsPanel";
			GameplaySettingsUI component = val2.GetComponent<GameplaySettingsUI>();
			_scroll = component.scroll;
			_content = (((Object)(object)_scroll != (Object)null) ? _scroll.content : null);
			if ((Object)(object)_content == (Object)null)
			{
				Plugin.Logger.LogWarning((object)"Gameplay tab has no scroll view, Mods tab not added");
				Object.Destroy((Object)(object)_templates);
				return false;
			}
			SliderSettingUI val3 = component.mouseSensitivity ?? component.horizontalSensitivity ?? component.verticalSensitivity;
			ToggleSettingUI val4 = component.invertYAxis ?? component.disableHeadBob ?? component.mouseInvertLook;
			object slider;
			if (!((Object)(object)val3 != (Object)null))
			{
				slider = null;
			}
			else
			{
				TextMeshProUGUI valueText = val3.valueText;
				slider = MakeTemplate((Component)(object)val3, (valueText != null) ? ((TMP_Text)valueText).transform : null);
			}
			_slider = (Template)slider;
			_toggle = (((Object)(object)val4 != (Object)null) ? MakeTemplate((Component)(object)val4, null) : null);
			object choice;
			if (!((Object)(object)component.language != (Object)null))
			{
				choice = null;
			}
			else
			{
				LanguageSettingUI language = component.language;
				TextMeshProUGUI choiceName = ((ChoiceSettingUI<Language>)(object)component.language).choiceName;
				choice = MakeTemplate((Component)(object)language, (choiceName != null) ? ((TMP_Text)choiceName).transform : null);
			}
			_choice = (Template)choice;
			if (_slider == null || _toggle == null)
			{
				Plugin.Logger.LogWarning((object)"Gameplay tab rows not found, Mods tab not added");
				Object.Destroy((Object)(object)_templates);
				return false;
			}
			_rowHeight = UiUtil.RowHeight(_slider.Go);
			Transform obj = UiUtil.Find(_slider.Go.transform, _slider.LabelPath);
			_headerStyle = ((obj != null) ? ((Component)obj).GetComponent<TextMeshProUGUI>() : null);
			SetUpButtons((SettingsTabPanel)(object)component);
			UiUtil.StripLocalization(val2);
			Object.DestroyImmediate((Object)(object)component);
			ClearContent();
			if ((Object)(object)((Component)_content).GetComponent<LayoutGroup>() == (Object)null)
			{
				VerticalLayoutGroup obj2 = ((Component)_content).gameObject.AddComponent<VerticalLayoutGroup>();
				((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true;
				((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false;
				((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true;
				((Component)_content).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
			}
			BuildRows();
			_panel = val2.AddComponent<UISubPanel>();
			_panel.fadeInTimeOverride = ((UISubPanel)val).fadeInTimeOverride;
			_panel.fadeOutTimeOverride = ((UISubPanel)val).fadeOutTimeOverride;
			_panel.ease = ((UISubPanel)val).ease;
			_panel.startVisible = false;
			_panel._canvasGroup = val2.GetComponent<CanvasGroup>();
			_panel._parentWindow_k__BackingField = ((UISubPanel)val)._parentWindow_k__BackingField;
			val2.transform.SetParent(((Component)val).transform.parent, false);
			val2.transform.SetSiblingIndex(((Component)val).transform.GetSiblingIndex() + 1);
			_panel.SetInvisibleImmediate();
			AddTabToggle();
			Plugin.Logger.LogInfo((object)"Mods tab added to the Settings window");
			return true;
		}

		private Template MakeTemplate(Component rowUi, Transform value)
		{
			Transform val = rowUi.transform;
			while ((Object)(object)UiUtil.FindLabel(val, value) == (Object)null && (Object)(object)val.parent != (Object)null && (Object)(object)val.parent != (Object)(object)_content)
			{
				val = val.parent;
			}
			TextMeshProUGUI val2 = UiUtil.FindLabel(val, value);
			Template obj = new Template
			{
				Go = ((Component)val).gameObject,
				LabelPath = (((Object)(object)val2 != (Object)null) ? UiUtil.PathFrom(val, ((TMP_Text)val2).transform) : null),
				ValuePath = UiUtil.PathFrom(val, value)
			};
			val.SetParent(_templates.transform, false);
			UiUtil.StripLocalization(obj.Go);
			UiUtil.StripSettingScripts(obj.Go);
			UiUtil.StripRowHelpers(obj.Go);
			return obj;
		}

		private void SetUpButtons(SettingsTabPanel copy)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			Button[] array = (Button[])(object)new Button[2] { copy.applyButton, copy.resetButton };
			foreach (Button val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					((Component)val).gameObject.SetActive(false);
				}
			}
			Button restoreDefaultsButton = copy.restoreDefaultsButton;
			if ((Object)(object)restoreDefaultsButton != (Object)null)
			{
				restoreDefaultsButton.onClick = new ButtonClickedEvent();
				((UnityEvent)restoreDefaultsButton.onClick).AddListener(UnityAction.op_Implicit((Action)ResetAll));
				((Selectable)restoreDefaultsButton).interactable = true;
			}
		}

		private void AddTabToggle()
		{
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Expected O, but got Unknown
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Expected O, but got Unknown
			Il2CppReferenceArray<Toggle> toggles = _controller.toggles;
			Il2CppReferenceArray<UISubPanel> panels = _controller.panels;
			Toggle val = ((Il2CppArrayBase<Toggle>)(object)toggles)[((Il2CppArrayBase<Toggle>)(object)toggles).Length - 1];
			GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, _templates.transform);
			((Object)val2).name = "NivalisModsTab";
			UiUtil.StripLocalization(val2);
			foreach (TextMeshProUGUI componentsInChild in val2.GetComponentsInChildren<TextMeshProUGUI>(true))
			{
				((TMP_Text)componentsInChild).text = "Mods";
			}
			Transform parent = ((Component)val).transform.parent;
			val2.transform.SetParent(parent, false);
			val2.transform.SetSiblingIndex(((Component)val).transform.GetSiblingIndex() + 1);
			if ((Object)(object)((Component)parent).GetComponent<LayoutGroup>() == (Object)null && ((Il2CppArrayBase<Toggle>)(object)toggles).Length >= 2)
			{
				RectTransform component = ((Component)((Il2CppArrayBase<Toggle>)(object)toggles)[((Il2CppArrayBase<Toggle>)(object)toggles).Length - 2]).GetComponent<RectTransform>();
				RectTransform component2 = ((Component)val).GetComponent<RectTransform>();
				val2.GetComponent<RectTransform>().anchoredPosition = component2.anchoredPosition + (component2.anchoredPosition - component.anchoredPosition);
			}
			_tabToggle = val2.GetComponent<Toggle>();
			_tabToggle.onValueChanged = new ToggleEvent();
			_tabToggle.SetIsOnWithoutNotify(false);
			int index = ((Il2CppArrayBase<Toggle>)(object)toggles).Length;
			Il2CppReferenceArray<Toggle> val3 = new Il2CppReferenceArray<Toggle>((long)(index + 1));
			Il2CppReferenceArray<UISubPanel> val4 = new Il2CppReferenceArray<UISubPanel>((long)(index + 1));
			for (int i = 0; i < index; i++)
			{
				((Il2CppArrayBase<Toggle>)(object)val3)[i] = ((Il2CppArrayBase<Toggle>)(object)toggles)[i];
				((Il2CppArrayBase<UISubPanel>)(object)val4)[i] = ((Il2CppArrayBase<UISubPanel>)(object)panels)[i];
			}
			((Il2CppArrayBase<Toggle>)(object)val3)[index] = _tabToggle;
			((Il2CppArrayBase<UISubPanel>)(object)val4)[index] = _panel;
			_controller.toggles = val3;
			_controller.panels = val4;
			if (_controller.events != null && _controller.events.Count == index)
			{
				_controller.events.Add(new UnityEvent());
			}
			WindowToggleController controller = _controller;
			((UnityEvent<bool>)(object)_tabToggle.onValueChanged).AddListener(UnityAction<bool>.op_Implicit((Action<bool>)delegate(bool on)
			{
				controller.ToggleValueChanged(on, index);
			}));
		}

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

		private void BuildRows()
		{
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			_rebinding = null;
			_refreshers.Clear();
			foreach (ConfigFile config in _configs)
			{
				config.SaveOnConfigSet = true;
			}
			_configs.Clear();
			ClearContent();
			List<ModPage> list = ModSettings.VisiblePages();
			bool flag = default(bool);
			foreach (ModPage item in list)
			{
				_configs.Add(item.Config);
				AddHeader(item.DisplayName, modTitle: true);
				List<(string, List<ModPage.Item>)> list2 = item.Layout();
				foreach (var (section, list3) in list2)
				{
					if (list2.Count > 1)
					{
						AddHeader(item.GetSectionLabel(section), modTitle: false);
					}
					foreach (ModPage.Item item2 in list3)
					{
						try
						{
							AddItem(item, item2);
						}
						catch (Exception ex)
						{
							ManualLogSource logger = Plugin.Logger;
							BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(24, 2, ref flag);
							if (flag)
							{
								((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not add setting ");
								ConfigEntryBase entry = item2.Entry;
								((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((entry != null) ? entry.Definition.Key : null) ?? item2.ButtonLabel);
								((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
								((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
							}
							logger.LogError(val);
						}
					}
				}
			}
			if (list.Count == 0)
			{
				AddHeader("No mods use the settings API", modTitle: false);
			}
			_builtVersion = ModSettings.Version;
			if ((Object)(object)_scroll != (Object)null)
			{
				_scroll.verticalNormalizedPosition = 1f;
			}
		}

		private void AddHeader(string text, bool modTitle)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Expected O, but got Unknown
			GameObject val = new GameObject(modTitle ? "ModTitle" : "Section");
			val.transform.SetParent((Transform)(object)_content, false);
			TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)_headerStyle != (Object)null)
			{
				((TMP_Text)val2).font = ((TMP_Text)_headerStyle).font;
				((TMP_Text)val2).fontSharedMaterial = ((TMP_Text)_headerStyle).fontSharedMaterial;
				((Graphic)val2).color = ((Graphic)_headerStyle).color;
				((TMP_Text)val2).fontSize = ((TMP_Text)_headerStyle).fontSize * (modTitle ? 1.35f : 1.05f);
			}
			((TMP_Text)val2).fontStyle = (FontStyles)(modTitle ? 17 : 2);
			((TMP_Text)val2).alignment = (TextAlignmentOptions)1025;
			((TMP_Text)val2).margin = new Vector4(modTitle ? 8f : 16f, 0f, 0f, 6f);
			((Graphic)val2).raycastTarget = false;
			((TMP_Text)val2).text = text;
			SetHeight(val, _rowHeight * (modTitle ? 1.3f : 0.9f));
		}

		private void AddItem(ModPage page, ModPage.Item item)
		{
			if (item.Entry == null)
			{
				AddButton(item.ButtonLabel, item.ButtonAction);
				return;
			}
			ConfigEntryBase entry = item.Entry;
			string label = page.GetLabel(entry);
			Type settingType = entry.SettingType;
			object[] options = GetOptions(entry);
			if (settingType == typeof(bool))
			{
				AddToggle(entry, label);
			}
			else if (options != null)
			{
				AddChoice(entry, label, options);
			}
			else if (settingType == typeof(float) || settingType == typeof(int) || settingType == typeof(double))
			{
				AddSlider(entry, label);
			}
			else if (settingType == typeof(string) && IsKeySetting(entry))
			{
				AddKey(entry, label);
			}
			else
			{
				AddReadOnly(entry, label);
			}
		}

		private GameObject Spawn(Template template, string label, out TextMeshProUGUI value)
		{
			GameObject val = Object.Instantiate<GameObject>(template.Go, (Transform)(object)_content);
			((Object)val).name = "Setting";
			val.SetActive(true);
			Transform obj = UiUtil.Find(val.transform, template.LabelPath);
			TextMeshProUGUI val2 = ((obj != null) ? ((Component)obj).GetComponent<TextMeshProUGUI>() : null);
			if ((Object)(object)val2 != (Object)null)
			{
				((TMP_Text)val2).text = label;
			}
			Transform obj2 = UiUtil.Find(val.transform, template.ValuePath);
			value = ((obj2 != null) ? ((Component)obj2).GetComponent<TextMeshProUGUI>() : null);
			SetHeight(val, _rowHeight);
			return val;
		}

		private static void SetHeight(GameObject go, float height)
		{
			//IL_0036: 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)
			LayoutElement obj = go.GetComponent<LayoutElement>() ?? go.AddComponent<LayoutElement>();
			obj.ignoreLayout = false;
			obj.minHeight = height;
			obj.preferredHeight = height;
			obj.flexibleHeight = 0f;
			RectTransform component = go.GetComponent<RectTransform>();
			component.sizeDelta = new Vector2(component.sizeDelta.x, height);
		}

		private void AddToggle(ConfigEntryBase entry, string label)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			TextMeshProUGUI value;
			GameObject val = Spawn(_toggle, label, out value);
			Toggle toggle = val.GetComponentInChildren<Toggle>(true);
			toggle.onValueChanged = new ToggleEvent();
			((UnityEvent<bool>)(object)toggle.onValueChanged).AddListener(UnityAction<bool>.op_Implicit((Action<bool>)delegate(bool on)
			{
				entry.BoxedValue = on;
			}));
			_refreshers.Add(delegate
			{
				toggle.SetIsOnWithoutNotify((bool)entry.BoxedValue);
			});
		}

		private void AddSlider(ConfigEntryBase entry, string label)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			TextMeshProUGUI valueText;
			GameObject val = Spawn(_slider, label, out valueText);
			Slider slider = val.GetComponentInChildren<Slider>(true);
			Type type = entry.SettingType;
			bool isInt = type == typeof(int);
			GetRange(entry, out var min, out var max);
			float range = max - min;
			slider.onValueChanged = new SliderEvent();
			slider.minValue = min;
			slider.maxValue = max;
			slider.wholeNumbers = isInt;
			((UnityEvent<float>)(object)slider.onValueChanged).AddListener(UnityAction<float>.op_Implicit((Action<float>)delegate(float v)
			{
				if (isInt)
				{
					entry.BoxedValue = Mathf.RoundToInt(v);
				}
				else if (type == typeof(double))
				{
					entry.BoxedValue = (double)RoundForRange(v, range);
				}
				else
				{
					entry.BoxedValue = RoundForRange(v, range);
				}
				Show(Convert.ToSingle(entry.BoxedValue));
			}));
			_refreshers.Add(delegate
			{
				float num = Convert.ToSingle(entry.BoxedValue);
				slider.SetValueWithoutNotify(num);
				Show(num);
			});
			void Show(float v)
			{
				if ((Object)(object)valueText != (Object)null)
				{
					((TMP_Text)valueText).text = FormatNumber(v, range, isInt);
				}
			}
		}

		private void AddChoice(ConfigEntryBase entry, string label, object[] options)
		{
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Expected O, but got Unknown
			Button[] array = null;
			TextMeshProUGUI valueText = null;
			GameObject val = null;
			if (_choice != null)
			{
				val = Spawn(_choice, label, out valueText);
				array = ((IEnumerable<Button>)val.GetComponentsInChildren<Button>(true)).OrderBy((Button b) => ((Component)b).transform.position.x).ToArray();
			}
			if (array == null || array.Length < 2 || (Object)(object)valueText == (Object)null)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
				val = Spawn(_slider, label, out valueText);
				Slider slider = val.GetComponentInChildren<Slider>(true);
				slider.onValueChanged = new SliderEvent();
				slider.minValue = 0f;
				slider.maxValue = options.Length - 1;
				slider.wholeNumbers = true;
				((UnityEvent<float>)(object)slider.onValueChanged).AddListener(UnityAction<float>.op_Implicit((Action<float>)delegate(float v)
				{
					entry.BoxedValue = options[Mathf.Clamp(Mathf.RoundToInt(v), 0, options.Length - 1)];
					if ((Object)(object)valueText != (Object)null)
					{
						((TMP_Text)valueText).text = entry.BoxedValue.ToString();
					}
				}));
				_refreshers.Add(delegate
				{
					slider.SetValueWithoutNotify((float)Current());
					if ((Object)(object)valueText != (Object)null)
					{
						((TMP_Text)valueText).text = entry.BoxedValue.ToString();
					}
				});
			}
			else
			{
				array[0].onClick = new ButtonClickedEvent();
				((UnityEvent)array[0].onClick).AddListener(UnityAction.op_Implicit((Action)delegate
				{
					Step(-1);
				}));
				array[^1].onClick = new ButtonClickedEvent();
				((UnityEvent)array[^1].onClick).AddListener(UnityAction.op_Implicit((Action)delegate
				{
					Step(1);
				}));
				_refreshers.Add(delegate
				{
					((TMP_Text)valueText).text = entry.BoxedValue.ToString();
				});
			}
			int Current()
			{
				return Math.Max(0, Array.FindIndex(options, (object o) => object.Equals(o, entry.BoxedValue)));
			}
			void Step(int delta)
			{
				int num = (Current() + delta + options.Length) % options.Length;
				entry.BoxedValue = options[num];
				((TMP_Text)valueText).text = options[num].ToString();
			}
		}

		private void AddKey(ConfigEntryBase entry, string label)
		{
			TextMeshProUGUI valueText = null;
			valueText = AddClickableRow(label, delegate
			{
				_rebinding = entry;
				_rebindRefresh = Refresh;
				Show();
			});
			_refreshers.Add(Show);
			void Show()
			{
				((TMP_Text)valueText).text = ((_rebinding == entry) ? "Press a key...  (Esc = cancel)" : $"[ {entry.BoxedValue} ]");
			}
		}

		private void AddButton(string label, Action action)
		{
			((TMP_Text)AddClickableRow(label, delegate
			{
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Expected O, but got Unknown
				try
				{
					action?.Invoke();
				}
				catch (Exception ex)
				{
					ManualLogSource logger = Plugin.Logger;
					bool flag = default(bool);
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(22, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Mod button '");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(label);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' failed: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
					}
					logger.LogError(val);
				}
				Refresh();
			})).text = "[ Run ]";
		}

		private void AddReadOnly(ConfigEntryBase entry, string label)
		{
			GameObject go;
			TextMeshProUGUI valueText = SpawnValueRow(label, out go);
			_refreshers.Add(delegate
			{
				((TMP_Text)valueText).text = entry.BoxedValue?.ToString() ?? "";
			});
		}

		private TextMeshProUGUI SpawnValueRow(string label, out GameObject go)
		{
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI value;
			if (_choice != null)
			{
				go = Spawn(_choice, label, out value);
				foreach (Button componentsInChild in go.GetComponentsInChildren<Button>(true))
				{
					((Component)componentsInChild).gameObject.SetActive(false);
				}
			}
			else
			{
				go = Spawn(_slider, label, out value);
				Slider component = go.GetComponent<Slider>();
				if ((Object)(object)component != (Object)null)
				{
					((Selectable)component).interactable = false;
				}
				Slider componentInChildren = go.GetComponentInChildren<Slider>(true);
				object obj;
				if (componentInChildren == null)
				{
					obj = null;
				}
				else
				{
					RectTransform fillRect = componentInChildren.fillRect;
					if (fillRect == null)
					{
						obj = null;
					}
					else
					{
						Transform parent = ((Transform)fillRect).parent;
						obj = ((parent != null) ? parent.parent : null);
					}
				}
				Transform val = (Transform)obj;
				if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)go.transform)
				{
					((Component)val).gameObject.SetActive(false);
				}
			}
			if ((Object)(object)value == (Object)null)
			{
				GameObject val2 = new GameObject("Value");
				val2.AddComponent<RectTransform>();
				val2.transform.SetParent(go.transform, false);
				value = val2.AddComponent<TextMeshProUGUI>();
				if ((Object)(object)_headerStyle != (Object)null)
				{
					((TMP_Text)value).font = ((TMP_Text)_headerStyle).font;
					((TMP_Text)value).fontSize = ((TMP_Text)_headerStyle).fontSize;
					((Graphic)value).color = ((Graphic)_headerStyle).color;
				}
				((TMP_Text)value).alignment = (TextAlignmentOptions)4100;
			}
			return value;
		}

		private TextMeshProUGUI AddClickableRow(string label, Action onClick)
		{
			//IL_000e: 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_001a: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			GameObject go;
			TextMeshProUGUI result = SpawnValueRow(label, out go);
			GameObject val = new GameObject("Click");
			RectTransform val2 = val.AddComponent<RectTransform>();
			val.transform.SetParent(go.transform, false);
			val2.anchorMin = Vector2.zero;
			val2.anchorMax = Vector2.one;
			val2.offsetMin = Vector2.zero;
			val2.offsetMax = Vector2.zero;
			val.AddComponent<LayoutElement>().ignoreLayout = true;
			((Graphic)val.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0f);
			Button obj = val.AddComponent<Button>();
			((Selectable)obj).transition = (Transition)0;
			obj.onClick = new ButtonClickedEvent();
			((UnityEvent)obj.onClick).AddListener(UnityAction.op_Implicit(onClick));
			return result;
		}

		private void ResetAll()
		{
			foreach (ModPage item in ModSettings.VisiblePages())
			{
				foreach (ConfigEntryBase item2 in item.VisibleEntries())
				{
					item2.BoxedValue = item2.DefaultValue;
				}
			}
			Refresh();
		}

		private unsafe void CaptureRebind()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			Keyboard current = Keyboard.current;
			if (current == null)
			{
				return;
			}
			if (((ButtonControl)current[(Key)60]).wasPressedThisFrame)
			{
				_rebinding = null;
				_rebindRefresh?.Invoke();
				return;
			}
			if (_keys == null)
			{
				_keys = BuildKeyList(current);
			}
			Key[] keys = _keys;
			for (int i = 0; i < keys.Length; i++)
			{
				Key val = keys[i];
				if (((ButtonControl)current[val]).wasPressedThisFrame)
				{
					_rebinding.BoxedValue = ((object)(*(Key*)(&val))/*cast due to .constrained prefix*/).ToString();
					_rebinding = null;
					_rebindRefresh?.Invoke();
					break;
				}
			}
		}

		private static Key[] BuildKeyList(Keyboard kb)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Invalid comparison between Unknown and I4
			//IL_0033: 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)
			List<Key> list = new List<Key>();
			foreach (Key value in Enum.GetValues(typeof(Key)))
			{
				if ((int)value == 0 || (int)value == 60)
				{
					continue;
				}
				try
				{
					if (kb[value] != null)
					{
						list.Add(value);
					}
				}
				catch (Exception)
				{
				}
			}
			return list.ToArray();
		}

		private static object[] GetOptions(ConfigEntryBase entry)
		{
			if (entry.SettingType.IsEnum)
			{
				return Enum.GetValues(entry.SettingType).Cast<object>().ToArray();
			}
			AcceptableValueBase acceptableValues = entry.Description.AcceptableValues;
			if (acceptableValues != null && ((object)acceptableValues).GetType().IsGenericType && ((object)acceptableValues).GetType().GetGenericTypeDefinition() == typeof(AcceptableValueList<>))
			{
				return (((object)acceptableValues).GetType().GetProperty("AcceptableValues")?.GetValue(acceptableValues) as Array)?.Cast<object>().ToArray();
			}
			return null;
		}

		private static bool IsKeySetting(ConfigEntryBase entry)
		{
			Key result;
			if (!entry.Definition.Key.EndsWith("Key"))
			{
				return Enum.TryParse<Key>((string)entry.BoxedValue, ignoreCase: true, out result);
			}
			return true;
		}

		private static void GetRange(ConfigEntryBase entry, out float min, out float max)
		{
			AcceptableValueBase acceptableValues = entry.Description.AcceptableValues;
			if (!(acceptableValues is AcceptableValueRange<float> val))
			{
				if (!(acceptableValues is AcceptableValueRange<int> val2))
				{
					if (acceptableValues is AcceptableValueRange<double> val3)
					{
						min = (float)val3.MinValue;
						max = (float)val3.MaxValue;
					}
					else
					{
						float num = Convert.ToSingle(entry.DefaultValue);
						min = Mathf.Min(0f, num * 4f);
						max = Mathf.Max(1f, Mathf.Abs(num) * 4f);
					}
				}
				else
				{
					min = val2.MinValue;
					max = val2.MaxValue;
				}
			}
			else
			{
				min = val.MinValue;
				max = val.MaxValue;
			}
		}

		private static float RoundForRange(float value, float range)
		{
			int digits = ((range <= 2f) ? 3 : ((range <= 20f) ? 2 : ((range <= 200f) ? 1 : 0)));
			return (float)Math.Round(value, digits);
		}

		private static string FormatNumber(float value, float range, bool isInt)
		{
			if (isInt)
			{
				return ((int)value).ToString();
			}
			if (!(range <= 2f))
			{
				if (!(range <= 20f))
				{
					return value.ToString("0.0");
				}
				return value.ToString("0.00");
			}
			return value.ToString("0.000");
		}
	}
	[BepInPlugin("com.asher.nivalissettings", "Nivalis Settings", "1.0.1")]
	public class Plugin : BasePlugin
	{
		public const string Guid = "com.asher.nivalissettings";

		public const string Version = "1.0.1";

		internal static ManualLogSource Logger;

		internal static ConfigEntry<bool> MenuButton;

		internal static ConfigEntry<bool> ShowAllPlugins;

		internal static ConfigEntry<bool> DumpUi;

		public override void Load()
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			Logger = ((BasePlugin)this).Log;
			MenuButton = ((BasePlugin)this).Config.Bind<bool>("Menu", "MenuButton", true, "Add a \"Mods\" button to the main/pause menu (takes effect when the menu is created).");
			ShowAllPlugins = ((BasePlugin)this).Config.Bind<bool>("Menu", "ShowAllPlugins", false, "Also list plugins that don't use the ModSettings API (shows all their config entries).");
			DumpUi = ((BasePlugin)this).Config.Bind<bool>("Debug", "DumpUi", false, "Write the Settings window hierarchy to the log when the Mods tab is built.");
			ModSettings.Register((BasePlugin)(object)this, "Mod Settings").Hide((ConfigEntryBase)(object)DumpUi);
			ClassInjector.RegisterTypeInIl2Cpp<ModsDriver>();
			((BasePlugin)this).AddComponent<ModsDriver>();
			new Harmony("com.asher.nivalissettings").PatchAll(typeof(MenuPatches));
			ManualLogSource log = ((BasePlugin)this).Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(24, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Nivalis Settings ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.0.1");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded");
			}
			log.LogInfo(val);
		}
	}
	internal static class UiUtil
	{
		public static void StripLocalization(GameObject go)
		{
			foreach (MonoBehaviour componentsInChild in go.GetComponentsInChildren<MonoBehaviour>(true))
			{
				if (!((Object)(object)componentsInChild == (Object)null))
				{
					string name = ((MemberInfo)((Object)componentsInChild).GetIl2CppType()).Name;
					if (name.Contains("Localiz") && !name.Contains("SetFont"))
					{
						Object.DestroyImmediate((Object)(object)componentsInChild);
					}
				}
			}
		}

		public static void StripSettingScripts(GameObject go)
		{
			foreach (SettingUIElementBase componentsInChild in go.GetComponentsInChildren<SettingUIElementBase>(true))
			{
				Object.DestroyImmediate((Object)(object)componentsInChild);
			}
		}

		public static void StripRowHelpers(GameObject go)
		{
			foreach (MonoBehaviour componentsInChild in go.GetComponentsInChildren<MonoBehaviour>(true))
			{
				if (!((Object)(object)componentsInChild == (Object)null))
				{
					bool flag;
					switch (((MemberInfo)((Object)componentsInChild).GetIl2CppType()).Name)
					{
					case "BetterContentSizeFitter":
					case "ContentSizeFitter":
					case "GamepadAutoScroll":
					case "ManualUINavigation":
						flag = true;
						break;
					default:
						flag = false;
						break;
					}
					if (flag)
					{
						Object.DestroyImmediate((Object)(object)componentsInChild);
					}
				}
			}
		}

		public static string PathFrom(Transform root, Transform t)
		{
			if ((Object)(object)t == (Object)null)
			{
				return null;
			}
			StringBuilder stringBuilder = new StringBuilder();
			while ((Object)(object)t != (Object)null && (Object)(object)t != (Object)(object)root)
			{
				stringBuilder.Insert(0, (stringBuilder.Length == 0) ? ((Object)t).name : (((Object)t).name + "/"));
				t = t.parent;
			}
			if (!((Object)(object)t == (Object)(object)root))
			{
				return null;
			}
			return stringBuilder.ToString();
		}

		public static Transform Find(Transform root, string path)
		{
			if (path == null)
			{
				return null;
			}
			if (path.Length != 0)
			{
				return root.Find(path);
			}
			return root;
		}

		public static TextMeshProUGUI FindLabel(Transform row, Transform exclude)
		{
			//IL_0052: 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)
			TextMeshProUGUI val = null;
			foreach (TextMeshProUGUI componentsInChild in ((Component)row).GetComponentsInChildren<TextMeshProUGUI>(true))
			{
				Transform transform = ((TMP_Text)componentsInChild).transform;
				if ((!((Object)(object)exclude != (Object)null) || (!((Object)(object)transform == (Object)(object)exclude) && !transform.IsChildOf(exclude))) && !((Object)(object)((Component)componentsInChild).GetComponentInParent<Button>() != (Object)null) && ((Object)(object)val == (Object)null || transform.position.x < ((TMP_Text)val).transform.position.x))
				{
					val = componentsInChild;
				}
			}
			return val;
		}

		public static float RowHeight(GameObject row)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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)
			LayoutElement component = row.GetComponent<LayoutElement>();
			if ((Object)(object)component != (Object)null && component.preferredHeight > 0f)
			{
				return component.preferredHeight;
			}
			RectTransform component2 = row.GetComponent<RectTransform>();
			if ((Object)(object)component2 != (Object)null)
			{
				Rect rect = component2.rect;
				if (((Rect)(ref rect)).height > 1f)
				{
					rect = component2.rect;
					return ((Rect)(ref rect)).height;
				}
			}
			return 48f;
		}

		public static void Dump(Transform t, StringBuilder sb, int depth = 0)
		{
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			sb.Append(' ', depth * 2).Append(((Object)t).name).Append(((Component)t).gameObject.activeSelf ? "" : " (off)")
				.Append(" [");
			foreach (Component component3 in ((Component)t).GetComponents<Component>())
			{
				sb.Append(((MemberInfo)((Object)component3).GetIl2CppType()).Name);
				Behaviour val = ((Il2CppObjectBase)component3).TryCast<Behaviour>();
				if ((Object)(object)val != (Object)null && !val.enabled)
				{
					sb.Append("(disabled)");
				}
				sb.Append(' ');
			}
			sb.Append("]");
			RectTransform component = ((Component)t).GetComponent<RectTransform>();
			if ((Object)(object)component != (Object)null)
			{
				StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(11, 2, sb);
				handler.AppendLiteral(" pos=");
				handler.AppendFormatted<Vector2>(component.anchoredPosition);
				handler.AppendLiteral(" size=");
				Rect rect = component.rect;
				handler.AppendFormatted<Vector2>(((Rect)(ref rect)).size);
				sb.Append(ref handler);
			}
			TextMeshProUGUI component2 = ((Component)t).GetComponent<TextMeshProUGUI>();
			if ((Object)(object)component2 != (Object)null)
			{
				sb.Append(" \"").Append(((TMP_Text)component2).text).Append('"');
			}
			sb.AppendLine();
			for (int i = 0; i < t.childCount; i++)
			{
				Dump(t.GetChild(i), sb, depth + 1);
			}
		}
	}
}