Decompiled source of Hotkey Helper v1.0.0

BepInEx/plugins/HotkeyHelper.dll

Decompiled a week 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.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("HotkeyHelper")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+2a4ecd46c7fc63775456bbd4b080666c3766eb88")]
[assembly: AssemblyProduct("HotkeyHelper")]
[assembly: AssemblyTitle("HotkeyHelper")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace HotkeyHelper;

[BepInPlugin("com.mous.hotkeyhelper", "Hotkey Helper", "1.0.0")]
public class HotkeyHelperPlugin : BaseUnityPlugin
{
	public const string PluginGuid = "com.mous.hotkeyhelper";

	public const string PluginName = "Hotkey Helper";

	public const string PluginVersion = "1.0.0";

	internal static HotkeyHelperPlugin Instance;

	internal static ConfigEntry<bool> Enabled;

	internal static ConfigEntry<int> MaxRows;

	internal static ConfigEntry<Vector2> ColumnPosition;

	internal static ConfigEntry<Vector2> InventoryColumnPosition;

	internal const int ColumnSortingOrder = 1000;

	internal static ConfigEntry<float> ColumnFontSize;

	internal static ConfigEntry<float> OverlayFontSize;

	internal static ConfigEntry<KeyboardShortcut> ShowAllKey;

	internal static ConfigEntry<bool> DebugDump;

	private Harmony _harmony;

	private void Awake()
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Expected O, but got Unknown
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Expected O, but got Unknown
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Expected O, but got Unknown
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Expected O, but got Unknown
		Instance = this;
		Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Enabled", true, "Show the mod hotkey column next to the vanilla key hints.");
		MaxRows = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "MaxRows", 15, new ConfigDescription("Max hotkeys listed in the side column.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 40), Array.Empty<object>()));
		ColumnPosition = ((BaseUnityPlugin)this).Config.Bind<Vector2>("2 - Layout", "ColumnPosition", new Vector2(0.995f, 0.4f), "Screen position of the column's right-middle point (0..1, x from left, y from bottom) while building/fighting.");
		InventoryColumnPosition = ((BaseUnityPlugin)this).Config.Bind<Vector2>("2 - Layout", "InventoryColumnPosition", new Vector2(0.995f, 0.09f), "Screen position of the column's bottom-right corner (column grows upward) while inventory, chest or crafting is open.");
		ColumnFontSize = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Layout", "ColumnFontSize", 14f, new ConfigDescription("Font size of the side column.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(8f, 32f), Array.Empty<object>()));
		OverlayFontSize = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Layout", "OverlayFontSize", 20f, new ConfigDescription("Max font size of the show-all list (shrinks to fit).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 36f), Array.Empty<object>()));
		ShowAllKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("1 - General", "ShowAllKey", new KeyboardShortcut((KeyCode)104, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Hold to show every discovered mod hotkey.");
		DebugDump = ((BaseUnityPlugin)this).Config.Bind<bool>("9 - Debug", "DumpOnWorldLoad", false, "Log the KeyHints UI hierarchy and all discovered hotkeys with their resolved contexts.");
		_harmony = new Harmony("com.mous.hotkeyhelper");
		_harmony.PatchAll();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Hotkey Helper 1.0.0 loaded");
	}

	private void Update()
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)Hud.instance == (Object)null))
		{
			int visible;
			if (Enabled.Value)
			{
				KeyboardShortcut value = ShowAllKey.Value;
				visible = (((KeyboardShortcut)(ref value)).IsPressed() ? 1 : 0);
			}
			else
			{
				visible = 0;
			}
			AllHotkeysOverlay.SetVisible((byte)visible != 0);
		}
	}

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

	internal static void Log(string msg)
	{
		((BaseUnityPlugin)Instance).Logger.LogInfo((object)msg);
	}

	internal static void Warn(string msg)
	{
		((BaseUnityPlugin)Instance).Logger.LogWarning((object)msg);
	}
}
internal sealed class Hotkey
{
	public string Guid;

	public string PluginName;

	public string Section;

	public string Key;

	public string Description;

	public string AutoContexts;

	public ConfigEntryBase Entry;

	public ConfigEntry<string> Override;

	public HashSet<string> Contexts = new HashSet<string>();

	public string Label;

	public string KeyText => HotkeyScanner.FormatBinding(Entry.BoxedValue);

	public bool IsGamepad => ((object)HotkeyScanner.MainKey(Entry.BoxedValue)/*cast due to .constrained prefix*/).ToString().StartsWith("Joystick");

	public bool IsBound => (int)HotkeyScanner.MainKey(Entry.BoxedValue) > 0;
}
internal static class HotkeyScanner
{
	public static readonly string[] AllContexts = new string[8] { "build", "buildmenu", "combat", "inventory", "container", "fishing", "radial", "general" };

	public static readonly List<Hotkey> Hotkeys = new List<Hotkey>();

	public static bool Dirty = true;

	private static readonly HashSet<ConfigFile> Subscribed = new HashSet<ConfigFile>();

	private static readonly (string guid, Regex key, string contexts)[] KnownMods = new(string, Regex, string)[6]
	{
		("shudnal.ExtraSlots", new Regex("^(Quickslot|Ammo|Food)", RegexOptions.IgnoreCase), "hidden"),
		("Snapheim.Valheim", new Regex(".*"), "build"),
		("Azumatt.AzuAutoStore", new Regex(".*"), "inventory,container"),
		("com.morda.storeandcraft", new Regex(".*"), "inventory,container"),
		("com.nopetrides.valheim.crop-utils", new Regex(".*"), "build"),
		("MK_BetterUI", new Regex(".*"), "general")
	};

	private static readonly (string context, Regex words)[] Keywords = new(string, Regex)[5]
	{
		("fishing", Words("fish")),
		("build", Words("build", "piece", "snap", "place", "rotat", "grid", "hammer", "terrain", "plant", "crop", "hoe", "cultivat")),
		("container", Words("container", "chest", "store", "dump", "take")),
		("inventory", Words("inventory", "craft", "recipe", "favo", "sort", "stack", "equip")),
		("combat", Words("attack", "weapon", "block", "dodge", "shield", "ammo", "bow"))
	};

	private static Regex Words(params string[] w)
	{
		return new Regex("\\b(" + string.Join("|", w) + ")", RegexOptions.IgnoreCase);
	}

	public static void Scan()
	{
		//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
		Hotkeys.Clear();
		ConfigFile config = ((BaseUnityPlugin)HotkeyHelperPlugin.Instance).Config;
		foreach (PluginInfo value2 in Chainloader.PluginInfos.Values)
		{
			if ((Object)(object)value2.Instance == (Object)null || value2.Metadata.GUID == "com.mous.hotkeyhelper")
			{
				continue;
			}
			ConfigFile config2 = value2.Instance.Config;
			if (Subscribed.Add(config2))
			{
				config2.SettingChanged += delegate
				{
					Dirty = true;
				};
			}
			foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in ((IEnumerable<KeyValuePair<ConfigDefinition, ConfigEntryBase>>)config2).ToList())
			{
				ConfigEntryBase value = item.Value;
				if (!(value.SettingType != typeof(KeyboardShortcut)) || !(value.SettingType != typeof(KeyCode)))
				{
					Hotkey obj = new Hotkey
					{
						Guid = value2.Metadata.GUID,
						PluginName = value2.Metadata.Name,
						Section = item.Key.Section,
						Key = item.Key.Key
					};
					ConfigDescription description = value.Description;
					obj.Description = ((description != null) ? description.Description : null) ?? "";
					obj.Entry = value;
					Hotkey hotkey = obj;
					hotkey.AutoContexts = AutoResolve(hotkey);
					hotkey.Override = config.Bind<string>(Sanitize("Hotkeys - " + hotkey.PluginName), Sanitize(hotkey.Section + " - " + hotkey.Key), "auto", "Where to show '" + hotkey.Key + "'. auto = " + hotkey.AutoContexts + ". Use auto, hidden, or a comma list of: " + string.Join(", ", AllContexts) + ". Optional custom label after ';' (e.g. build;Cycle snap).");
					Resolve(hotkey);
					Hotkeys.Add(hotkey);
				}
			}
		}
		if (Subscribed.Add(config))
		{
			config.SettingChanged += delegate
			{
				Dirty = true;
			};
		}
		Dirty = true;
		string showAll = FormatBinding(HotkeyHelperPlugin.ShowAllKey.Value);
		foreach (Hotkey item2 in Hotkeys.Where((Hotkey h) => h.IsBound && h.KeyText == showAll))
		{
			HotkeyHelperPlugin.Warn("ShowAllKey (" + showAll + ") is also bound by " + item2.PluginName + ": " + item2.Key);
		}
	}

	public static IEnumerable<Hotkey> Visible(bool gamepad)
	{
		return Hotkeys.Where((Hotkey h) => h.IsBound && h.IsGamepad == gamepad && !h.Contexts.Contains("hidden"));
	}

	public static void ResolveAll()
	{
		foreach (Hotkey hotkey in Hotkeys)
		{
			Resolve(hotkey);
		}
	}

	private static void Resolve(Hotkey hk)
	{
		string[] array = (hk.Override.Value ?? "auto").Split(new char[1] { ';' }, 2);
		string text = array[0].Trim();
		if (text == "" || text.Equals("auto", StringComparison.OrdinalIgnoreCase))
		{
			text = hk.AutoContexts;
		}
		hk.Contexts = new HashSet<string>(from c in text.ToLowerInvariant().Split(new char[1] { ',' })
			select c.Trim() into c
			where c != ""
			select c);
		hk.Label = ((array.Length > 1 && array[1].Trim() != "") ? array[1].Trim() : Humanize(hk.Key, hk.PluginName));
	}

	internal static string AutoResolve(Hotkey hk)
	{
		(string, Regex, string)[] knownMods = KnownMods;
		for (int i = 0; i < knownMods.Length; i++)
		{
			var (text, regex, result) = knownMods[i];
			if (text == hk.Guid && regex.IsMatch(hk.Key))
			{
				return result;
			}
		}
		string[] array = new string[2]
		{
			hk.Section + " " + hk.Key + " " + hk.PluginName,
			hk.Description
		};
		foreach (string text2 in array)
		{
			List<string> list = (from k in Keywords
				where k.words.IsMatch(text2)
				select k.context).ToList();
			if (list.Count > 0)
			{
				return string.Join(",", list);
			}
		}
		return "general";
	}

	internal static string Humanize(string key, string fallback)
	{
		string input = Regex.Replace(key, "(?<=[a-z])(?=[A-Z])", " ");
		input = Regex.Replace(input, "(\\s*(hot\\s*key|short\\s*cut|key\\s*bind\\d*|key|gamepad))+\\s*$", "", RegexOptions.IgnoreCase).Trim();
		if (input == "")
		{
			return fallback;
		}
		return char.ToUpperInvariant(input[0]) + input.Substring(1);
	}

	private static string Sanitize(string s)
	{
		return Regex.Replace(s, "[=\\n\\t\\\\\"'\\[\\]]", " ");
	}

	internal static KeyCode MainKey(object binding)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: 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_001a: 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_0024: 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_0032: 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_002d: Unknown result type (might be due to invalid IL or missing references)
		if (!(binding is KeyboardShortcut val))
		{
			if (binding is KeyCode result)
			{
				return result;
			}
			return (KeyCode)0;
		}
		return ((KeyboardShortcut)(ref val)).MainKey;
	}

	internal static string FormatBinding(object binding)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		if (binding is KeyboardShortcut val)
		{
			return string.Join(" + ", ((KeyboardShortcut)(ref val)).Modifiers.Select(KeyName).Concat(new string[1] { KeyName(((KeyboardShortcut)(ref val)).MainKey) }));
		}
		if (!(binding is KeyCode k))
		{
			return "";
		}
		return KeyName(k);
	}

	internal unsafe static string KeyName(KeyCode k)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Invalid comparison between Unknown and I4
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Invalid comparison between Unknown and I4
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Expected I4, but got Unknown
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Expected I4, but got Unknown
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Invalid comparison between Unknown and I4
		//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_007d: Expected I4, but got Unknown
		if ((int)k <= 59)
		{
			switch (k - 39)
			{
			default:
				if ((int)k != 59)
				{
					break;
				}
				return ";";
			case 7:
				return ".";
			case 5:
				return ",";
			case 6:
				return "-";
			case 4:
				return "+";
			case 8:
				return "/";
			case 0:
				return "'";
			case 1:
			case 2:
			case 3:
				break;
			}
		}
		else
		{
			if ((int)k == 61)
			{
				return "=";
			}
			switch (k - 91)
			{
			default:
				switch (k - 323)
				{
				case 0:
					return "LMB";
				case 1:
					return "RMB";
				case 2:
					return "MMB";
				}
				break;
			case 0:
				return "[";
			case 2:
				return "]";
			case 1:
				return "\\";
			case 5:
				return "`";
			case 3:
			case 4:
				break;
			}
		}
		string text = ((object)(*(KeyCode*)(&k))/*cast due to .constrained prefix*/).ToString();
		if (text.StartsWith("Alpha"))
		{
			return text.Substring(5);
		}
		if (text.StartsWith("Keypad"))
		{
			return "Num" + text.Substring(6);
		}
		if (text.StartsWith("Joystick"))
		{
			return "Pad " + text.Substring(text.IndexOf("Button") + 6);
		}
		return text.Replace("Left", "L").Replace("Right", "R").Replace("Control", "Ctrl");
	}
}
[HarmonyPatch(typeof(KeyHints))]
internal static class ContextColumn
{
	private static GameObject _root;

	private static TextMeshProUGUI _text;

	private static string _lastKey;

	[HarmonyPostfix]
	[HarmonyPatch("Start")]
	private static void Start()
	{
		ConfigFile config = ((BaseUnityPlugin)HotkeyHelperPlugin.Instance).Config;
		config.SaveOnConfigSet = false;
		HotkeyScanner.Scan();
		config.Save();
		config.SaveOnConfigSet = true;
		_lastKey = null;
		if (HotkeyHelperPlugin.DebugDump.Value)
		{
			HotkeyHelperPlugin.Log("Discovered hotkeys:\n" + string.Join("\n", HotkeyScanner.Hotkeys.Select((Hotkey hk) => "  " + hk.PluginName + " | [" + hk.Section + "] " + hk.Key + " = " + hk.KeyText + " | auto=" + hk.AutoContexts + " | shown=" + string.Join(",", hk.Contexts) + " | label=" + hk.Label)));
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch("UpdateHints")]
	private static void UpdateHints(KeyHints __instance)
	{
		//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_0124: 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_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		string[] contexts = ActiveContexts(__instance);
		bool gamepad = ZInput.IsGamepadActive();
		string text = ((contexts == null || !HotkeyHelperPlugin.Enabled.Value || AllHotkeysOverlay.Visible) ? null : (string.Join(",", contexts) + gamepad));
		if (text == _lastKey && !HotkeyScanner.Dirty)
		{
			return;
		}
		_lastKey = text;
		HotkeyScanner.Dirty = false;
		HotkeyScanner.ResolveAll();
		List<Hotkey> list = ((text == null) ? new List<Hotkey>() : (from h in HotkeyScanner.Visible(gamepad)
			where contexts.Any(h.Contexts.Contains)
			select h).Take(HotkeyHelperPlugin.MaxRows.Value).ToList());
		if (list.Count == 0)
		{
			if (Object.op_Implicit((Object)(object)_root))
			{
				_root.SetActive(false);
			}
		}
		else if (Object.op_Implicit((Object)(object)_root) || Create())
		{
			bool flag = contexts.Contains("inventory");
			RectTransform val = (RectTransform)_root.transform;
			val.pivot = (flag ? new Vector2(1f, 0f) : new Vector2(1f, 0.5f));
			Vector2 anchorMin = (val.anchorMax = (flag ? HotkeyHelperPlugin.InventoryColumnPosition : HotkeyHelperPlugin.ColumnPosition).Value);
			val.anchorMin = anchorMin;
			((TMP_Text)_text).fontSize = HotkeyHelperPlugin.ColumnFontSize.Value;
			((TMP_Text)_text).text = string.Join("\n", list.Select((Hotkey h) => h.Label + "  <color=#ffd27f>" + h.KeyText + "</color>"));
			_root.SetActive(true);
		}
	}

	private static string[] ActiveContexts(KeyHints kh)
	{
		if (kh.m_buildHints.activeSelf)
		{
			if (Hud.IsPieceSelectionVisible())
			{
				return new string[2] { "build", "buildmenu" };
			}
			return new string[1] { "build" };
		}
		if (kh.m_combatHints.activeSelf)
		{
			return new string[1] { "combat" };
		}
		if (kh.m_inventoryWithContainerHints.activeSelf)
		{
			return new string[2] { "inventory", "container" };
		}
		if (kh.m_inventoryHints.activeSelf)
		{
			return new string[1] { "inventory" };
		}
		if (kh.m_fishingHints.activeSelf)
		{
			return new string[1] { "fishing" };
		}
		if (kh.m_radialHints.activeSelf)
		{
			return new string[1] { "radial" };
		}
		return null;
	}

	private static bool Create()
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Expected O, but got Unknown
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Expected O, but got Unknown
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Expected O, but got Unknown
		if (!Ui.TryGetFont(out var font))
		{
			return false;
		}
		_root = new GameObject("HotkeyHelperColumn", new Type[4]
		{
			typeof(RectTransform),
			typeof(Image),
			typeof(VerticalLayoutGroup),
			typeof(ContentSizeFitter)
		});
		RectTransform val = (RectTransform)_root.transform;
		((Transform)val).SetParent(Hud.instance.m_rootObject.transform, false);
		Canvas obj = _root.AddComponent<Canvas>();
		obj.overrideSorting = true;
		obj.sortingOrder = 1000;
		((Graphic)_root.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.45f);
		VerticalLayoutGroup component = _root.GetComponent<VerticalLayoutGroup>();
		((LayoutGroup)component).padding = new RectOffset(10, 10, 6, 6);
		bool childControlWidth = (((HorizontalOrVerticalLayoutGroup)component).childControlHeight = true);
		((HorizontalOrVerticalLayoutGroup)component).childControlWidth = childControlWidth;
		ContentSizeFitter component2 = _root.GetComponent<ContentSizeFitter>();
		FitMode horizontalFit = (FitMode)2;
		component2.verticalFit = (FitMode)2;
		component2.horizontalFit = horizontalFit;
		_text = Ui.Text((Transform)val, font);
		((TMP_Text)_text).alignment = (TextAlignmentOptions)516;
		return true;
	}
}
internal static class AllHotkeysOverlay
{
	private static GameObject _root;

	private static TextMeshProUGUI _left;

	private static TextMeshProUGUI _right;

	public static bool Visible
	{
		get
		{
			if (Object.op_Implicit((Object)(object)_root))
			{
				return _root.activeSelf;
			}
			return false;
		}
	}

	public static void SetVisible(bool visible)
	{
		if (!visible)
		{
			if (Object.op_Implicit((Object)(object)_root))
			{
				_root.SetActive(false);
			}
		}
		else
		{
			if (Visible || (!Object.op_Implicit((Object)(object)_root) && !Create()))
			{
				return;
			}
			HotkeyScanner.ResolveAll();
			List<Hotkey> list = HotkeyScanner.Visible(ZInput.IsGamepadActive()).ToList();
			float keyWidthEm = ((list.Count == 0) ? 4f : ((float)list.Max((Hotkey h) => h.KeyText.Length) * 0.6f + 1f));
			List<List<string>> list2 = (from h in list
				group h by h.PluginName into g
				select new string[1] { "<color=#ffc34d><b>" + g.Key + "</b></color>" }.Concat(g.Select((Hotkey h) => string.Format("<color=#ffffff>{0}</color><pos={1:0.#}em>{2}  <size=75%><color=#8a8a8a>{3}</color></size>", h.KeyText, keyWidthEm, h.Label, string.Join(", ", h.Contexts)))).Concat(new string[1] { "" }).ToList()).ToList();
			int num = list2.Sum((List<string> g) => g.Count);
			int num2 = 0;
			List<string> list3 = new List<string>();
			List<string> list4 = new List<string>();
			foreach (List<string> item in list2)
			{
				if (list4.Count == 0 && num2 + item.Count / 2 <= num / 2)
				{
					list3.AddRange(item);
					num2 += item.Count;
				}
				else
				{
					list4.AddRange(item);
				}
			}
			((TMP_Text)_left).text = ((list.Count == 0) ? "No mod hotkeys found." : string.Join("\n", list3));
			((TMP_Text)_right).text = string.Join("\n", list4);
			_root.SetActive(true);
			TextMeshProUGUI[] array = (TextMeshProUGUI[])(object)new TextMeshProUGUI[2] { _left, _right };
			foreach (TextMeshProUGUI obj in array)
			{
				((TMP_Text)obj).enableAutoSizing = true;
				((TMP_Text)obj).fontSizeMax = HotkeyHelperPlugin.OverlayFontSize.Value;
				((TMP_Text)obj).ForceMeshUpdate(false, false);
			}
			float fontSize = Mathf.Min(((TMP_Text)_left).fontSize, (((TMP_Text)_right).text == "") ? ((TMP_Text)_left).fontSize : ((TMP_Text)_right).fontSize);
			array = (TextMeshProUGUI[])(object)new TextMeshProUGUI[2] { _left, _right };
			foreach (TextMeshProUGUI obj2 in array)
			{
				((TMP_Text)obj2).enableAutoSizing = false;
				((TMP_Text)obj2).fontSize = fontSize;
			}
		}
	}

	private static bool Create()
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Expected O, but got Unknown
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: 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_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: 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_00bb: 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_00cc: Expected O, but got Unknown
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Expected O, but got Unknown
		//IL_0141: Expected O, but got Unknown
		if (!Ui.TryGetFont(out var font))
		{
			return false;
		}
		_root = new GameObject("HotkeyHelperOverlay", new Type[2]
		{
			typeof(RectTransform),
			typeof(Image)
		});
		RectTransform val = (RectTransform)_root.transform;
		((Transform)val).SetParent(Hud.instance.m_rootObject.transform, false);
		val.anchorMin = new Vector2(0.12f, 0.08f);
		val.anchorMax = new Vector2(0.88f, 0.92f);
		Vector2 offsetMin = (val.offsetMax = Vector2.zero);
		val.offsetMin = offsetMin;
		((Graphic)_root.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.85f);
		TextMeshProUGUI obj = Ui.Text((Transform)val, font);
		((TMP_Text)obj).text = "<b>Mod hotkeys</b>";
		((TMP_Text)obj).fontSize = 28f;
		((Graphic)obj).color = new Color(1f, 0.82f, 0.45f);
		Place(((TMP_Text)obj).rectTransform, 0f, 1f, 16f, -60f, fromTop: true);
		_left = Column(val, font, 0f, 0.5f);
		_right = Column(val, font, 0.5f, 1f);
		_root.SetActive(false);
		return true;
	}

	private static TextMeshProUGUI Column(RectTransform parent, TMP_FontAsset font, float xMin, float xMax)
	{
		TextMeshProUGUI obj = Ui.Text((Transform)(object)parent, font);
		((TMP_Text)obj).fontSizeMin = 10f;
		((TMP_Text)obj).overflowMode = (TextOverflowModes)3;
		Place(((TMP_Text)obj).rectTransform, xMin, xMax, 70f, 24f, fromTop: false);
		return obj;
	}

	private static void Place(RectTransform rt, float xMin, float xMax, float top, float bottom, bool fromTop)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		rt.anchorMin = new Vector2(xMin, fromTop ? 1f : 0f);
		rt.anchorMax = new Vector2(xMax, 1f);
		rt.offsetMin = new Vector2(32f, bottom);
		rt.offsetMax = new Vector2(-32f, 0f - top);
	}
}
internal static class Ui
{
	public static bool TryGetFont(out TMP_FontAsset font)
	{
		font = ((Object.op_Implicit((Object)(object)KeyHints.instance) && Object.op_Implicit((Object)(object)KeyHints.instance.m_buildMenuKey)) ? ((TMP_Text)KeyHints.instance.m_buildMenuKey).font : null);
		if ((Object)(object)Hud.instance != (Object)null)
		{
			return (Object)(object)font != (Object)null;
		}
		return false;
	}

	public static TextMeshProUGUI Text(Transform parent, TMP_FontAsset font)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Text", new Type[2]
		{
			typeof(RectTransform),
			typeof(TextMeshProUGUI)
		});
		val.transform.SetParent(parent, false);
		TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
		((TMP_Text)component).font = font;
		((TMP_Text)component).richText = true;
		((Graphic)component).color = new Color(0.9f, 0.9f, 0.9f);
		((TMP_Text)component).textWrappingMode = (TextWrappingModes)0;
		return component;
	}
}