Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of NathansQol KeyBindings v0.2.2
NathansQol.KeyBindings.dll
Decompiled 6 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.DualShock; using UnityEngine.InputSystem.Layouts; using UnityEngine.UI; using Valheim.SettingsGui; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_guiutils")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("NateBuzz")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Public API of the NathansQol_KeyBindings mod for Valheim: lets mods list their hotkeys in the Key Bindings tab of the game settings.")] [assembly: AssemblyFileVersion("0.2.2.0")] [assembly: AssemblyInformationalVersion("0.2.2+56e9e83bf8f8eae3fe1e338d2b74ef4717eb2ed6")] [assembly: AssemblyProduct("NathansQol.KeyBindings")] [assembly: AssemblyTitle("NathansQol.KeyBindings")] [assembly: AssemblyMetadata("RepositoryUrl", "https://gitlab.com/nathans-norse-niceties/keybindings-mod.git")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.2.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace NathansQol.KeyBindings { public enum GamepadButton { None, DPadUp, DPadDown, DPadLeft, DPadRight, ButtonSouth, ButtonEast, ButtonWest, ButtonNorth, LeftShoulder, RightShoulder, LeftTrigger, RightTrigger, LeftStickButton, RightStickButton, Start, Select } public sealed class KeyBinding { private readonly KeySource _source; private readonly string _configKey; private GamepadButton[] _gamepad; private ConfigEntry<string> _gamepadEntry; private string _gamepadText; private GamepadButton[] _gamepadParsed; public string Label { get; } public string ModName { get; } public string ModGuid { get; } public GamepadButton Gamepad { get { if (GamepadButtons.Count <= 0) { return GamepadButton.None; } return GamepadButtons[0]; } } public IReadOnlyList<GamepadButton> GamepadButtons { get { if (_gamepadEntry == null) { return _gamepad; } string value = _gamepadEntry.Value; if ((object)value != _gamepadText && value != _gamepadText) { _gamepadText = value; _gamepadParsed = ChordText.Parse(value); } return _gamepadParsed; } } public GamepadButton DefaultGamepad { get { if (DefaultGamepadButtons.Length == 0) { return GamepadButton.None; } return DefaultGamepadButtons[0]; } } public GamepadButton[] DefaultGamepadButtons { get; } internal KeySource Source => _source; public event Action Changed; internal KeyBinding(string modGuid, string modName, string label, KeySource source, GamepadButton[] defaultGamepad) { ModGuid = modGuid; ModName = modName; Label = label; DefaultGamepadButtons = defaultGamepad; _source = source; _gamepad = defaultGamepad; _configKey = Registry.ConfigKey(modGuid, source.Id); } public bool IsDown() { if (!_source.IsDown()) { return GamepadInput.IsDown(GamepadButtons); } return true; } public bool IsPressed() { if (!_source.IsPressed()) { return GamepadInput.IsPressed(GamepadButtons); } return true; } public bool IsUp() { if (!_source.IsUp()) { return GamepadInput.IsUp(GamepadButtons); } return true; } internal void SetGamepad(GamepadButton button) { SetGamepadChord((button == GamepadButton.None) ? ChordText.None : new GamepadButton[1] { button }); } internal void SetGamepadChord(IReadOnlyList<GamepadButton> buttons) { GamepadButton[] array = buttons.Where((GamepadButton b) => b != GamepadButton.None).Distinct().Take(3) .ToArray(); if (_gamepadEntry != null) { _gamepadEntry.Value = ChordText.Format(array); } else { _gamepad = array; } } internal void BindConfig(ConfigFile file) { if (_gamepadEntry == null) { _gamepadEntry = file.Bind<string>("Controller", _configKey, ChordText.Format(_gamepad), "Controller button (or buttons held together, joined by +) for '" + Label + "' of " + ModName + ". Change it in the Key Bindings tab of the game settings."); } } internal void NotifyChanged() { this.Changed?.Invoke(); } } public static class KeyBindings { public const int ApiVersion = 2; public static KeyBinding Register(PluginInfo plugin, ConfigEntry<KeyboardShortcut> shortcut, string label, GamepadButton defaultGamepad = GamepadButton.None) { if (plugin == null) { throw new ArgumentNullException("plugin"); } return Register(plugin.Metadata.GUID, plugin.Metadata.Name, shortcut, label, defaultGamepad); } public static KeyBinding Register(PluginInfo plugin, ConfigEntry<KeyCode> key, string label, GamepadButton defaultGamepad = GamepadButton.None) { if (plugin == null) { throw new ArgumentNullException("plugin"); } return Register(plugin.Metadata.GUID, plugin.Metadata.Name, key, label, defaultGamepad); } public static KeyBinding Register(string modGuid, string modName, ConfigEntry<KeyboardShortcut> shortcut, string label, GamepadButton defaultGamepad = GamepadButton.None) { if (shortcut == null) { throw new ArgumentNullException("shortcut"); } return Registry.Add(modGuid, modName, new ShortcutSource(shortcut), label, Single(defaultGamepad)); } public static KeyBinding Register(string modGuid, string modName, ConfigEntry<KeyCode> key, string label, GamepadButton defaultGamepad = GamepadButton.None) { if (key == null) { throw new ArgumentNullException("key"); } return Registry.Add(modGuid, modName, new KeyCodeSource(key), label, Single(defaultGamepad)); } public static KeyBinding Register(PluginInfo plugin, ConfigEntry<KeyboardShortcut> shortcut, string label, string defaultGamepad) { if (plugin == null) { throw new ArgumentNullException("plugin"); } if (shortcut == null) { throw new ArgumentNullException("shortcut"); } return Registry.Add(plugin.Metadata.GUID, plugin.Metadata.Name, new ShortcutSource(shortcut), label, ChordText.Parse(defaultGamepad)); } public static KeyBinding Register(PluginInfo plugin, ConfigEntry<KeyCode> key, string label, string defaultGamepad) { if (plugin == null) { throw new ArgumentNullException("plugin"); } if (key == null) { throw new ArgumentNullException("key"); } return Registry.Add(plugin.Metadata.GUID, plugin.Metadata.Name, new KeyCodeSource(key), label, ChordText.Parse(defaultGamepad)); } private static GamepadButton[] Single(GamepadButton button) { if (button != GamepadButton.None) { return new GamepadButton[1] { button }; } return ChordText.None; } } internal static class ChordText { public static readonly GamepadButton[] None = new GamepadButton[0]; public static string Format(IReadOnlyList<GamepadButton> chord) { if (chord != null && chord.Count != 0) { return string.Join("+", chord.Select((GamepadButton b) => b.ToString())); } return "None"; } public static GamepadButton[] Parse(string text) { if (string.IsNullOrWhiteSpace(text)) { return None; } List<GamepadButton> list = new List<GamepadButton>(); string[] array = text.Split('+', ','); for (int i = 0; i < array.Length; i++) { if (Enum.TryParse<GamepadButton>(array[i].Trim(), ignoreCase: true, out var result) && result != GamepadButton.None && !list.Contains(result)) { list.Add(result); } } return list.Take(3).ToArray(); } } internal static class GamepadInput { internal enum Family { Xbox, PlayStation, Nintendo } public static readonly GamepadButton[] Bindable = ((GamepadButton[])Enum.GetValues(typeof(GamepadButton))).Where((GamepadButton b) => b != GamepadButton.None).ToArray(); public const int MaxChord = 3; public static bool IsDown(GamepadButton button) { ButtonControl val = Control(button); if (val != null) { return val.wasPressedThisFrame; } return false; } public static bool IsPressed(GamepadButton button) { ButtonControl val = Control(button); if (val != null) { return val.isPressed; } return false; } public static bool IsUp(GamepadButton button) { ButtonControl val = Control(button); if (val != null) { return val.wasReleasedThisFrame; } return false; } public static bool IsDown(IReadOnlyList<GamepadButton> chord) { if (!IsPressed(chord)) { return false; } foreach (GamepadButton item in chord) { if (IsDown(item)) { return true; } } return false; } public static bool IsPressed(IReadOnlyList<GamepadButton> chord) { if (chord == null || chord.Count == 0) { return false; } foreach (GamepadButton item in chord) { if (!IsPressed(item)) { return false; } } return true; } public static bool IsUp(IReadOnlyList<GamepadButton> chord) { if (chord == null || chord.Count == 0) { return false; } bool result = false; foreach (GamepadButton item in chord) { if (IsUp(item)) { result = true; } else if (!IsPressed(item)) { return false; } } return result; } public static List<GamepadButton> HeldNow() { return Bindable.Where(IsPressed).Take(3).ToList(); } public static string Name(IReadOnlyList<GamepadButton> chord) { if (chord != null && chord.Count != 0) { return string.Join(" + ", chord.Select(Name)); } return "-"; } public static GamepadButton PressedThisFrame() { GamepadButton[] bindable = Bindable; foreach (GamepadButton gamepadButton in bindable) { if (IsDown(gamepadButton)) { return gamepadButton; } } return GamepadButton.None; } public static string Name(GamepadButton button) { if (button == GamepadButton.None) { return "-"; } Family num = CurrentFamily(); bool flag = num == Family.PlayStation; bool flag2 = num == Family.Nintendo; switch (button) { case GamepadButton.DPadUp: return "D-pad Up"; case GamepadButton.DPadDown: return "D-pad Down"; case GamepadButton.DPadLeft: return "D-pad Left"; case GamepadButton.DPadRight: return "D-pad Right"; case GamepadButton.ButtonSouth: if (!flag) { if (!flag2) { return "A"; } return "B"; } return "Cross"; case GamepadButton.ButtonEast: if (!flag) { if (!flag2) { return "B"; } return "A"; } return "Circle"; case GamepadButton.ButtonWest: if (!flag) { if (!flag2) { return "X"; } return "Y"; } return "Square"; case GamepadButton.ButtonNorth: if (!flag) { if (!flag2) { return "Y"; } return "X"; } return "Triangle"; case GamepadButton.LeftShoulder: if (!flag) { if (!flag2) { return "LB"; } return "L"; } return "L1"; case GamepadButton.RightShoulder: if (!flag) { if (!flag2) { return "RB"; } return "R"; } return "R1"; case GamepadButton.LeftTrigger: if (!flag) { if (!flag2) { return "LT"; } return "ZL"; } return "L2"; case GamepadButton.RightTrigger: if (!flag) { if (!flag2) { return "RT"; } return "ZR"; } return "R2"; case GamepadButton.LeftStickButton: if (!flag) { return "Left Stick"; } return "L3"; case GamepadButton.RightStickButton: if (!flag) { return "Right Stick"; } return "R3"; case GamepadButton.Start: if (!flag) { if (!flag2) { return "Menu"; } return "+"; } return "Options"; case GamepadButton.Select: if (!flag) { if (!flag2) { return "View"; } return "-"; } return "Share"; default: return button.ToString(); } } private static Family CurrentFamily() { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) switch (KeyBindingsPlugin.ControllerLayout?.Value) { case "Xbox": return Family.Xbox; case "PlayStation": return Family.PlayStation; case "Nintendo": return Family.Nintendo; default: { try { switch (GameGamepadType()) { case "DualShock": case "DualSense": return Family.PlayStation; case "SwitchPro": case "JoyCon": case "JoyCon2Mouse": return Family.Nintendo; } } catch (Exception) { } Gamepad current = Gamepad.current; if (current == null) { return Family.Xbox; } if (current is DualShockGamepad) { return Family.PlayStation; } string name = ((object)current).GetType().Name; InputDeviceDescription description = ((InputDevice)current).description; return FamilyFromName(name + " " + ((InputDeviceDescription)(ref description)).product); } } } internal static Family FamilyFromName(string name) { string text = (name ?? "").ToLowerInvariant(); if (text.Contains("xbox") || text.Contains("xinput")) { return Family.Xbox; } if (text.Contains("dualshock") || text.Contains("dualsense") || text.Contains("playstation") || text.Contains("ps3") || text.Contains("ps4") || text.Contains("ps5") || text.Contains("wireless controller") || text.Contains("sony")) { return Family.PlayStation; } if (text.Contains("switch") || text.Contains("pro controller") || text.Contains("joy-con") || text.Contains("joycon") || text.Contains("nintendo")) { return Family.Nintendo; } return Family.Xbox; } public static string Describe() { //IL_004d: 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) //IL_0066: 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) string text; try { text = GameGamepadType() ?? "none"; } catch (Exception) { text = "unavailable"; } Gamepad current = Gamepad.current; string text2 = text; object obj2; if (current != null) { string[] obj = new string[5] { ((object)current).GetType().Name, " / ", null, null, null }; InputDeviceDescription description = ((InputDevice)current).description; obj[2] = ((InputDeviceDescription)(ref description)).product; obj[3] = " / "; description = ((InputDevice)current).description; obj[4] = ((InputDeviceDescription)(ref description)).interfaceName; obj2 = string.Concat(obj); } else { obj2 = "no gamepad"; } return "game: " + text2 + "; Unity: " + (string?)obj2; } [MethodImpl(MethodImplOptions.NoInlining)] private static string GameGamepadType() { //IL_0016: 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) ZInput instance = ZInput.instance; if (instance == null) { return null; } PlatformGamepadDefinition definition = instance.m_definition; if (definition == null) { return null; } return ((object)definition.GetConnectedGamepadType()/*cast due to .constrained prefix*/).ToString(); } private static ButtonControl Control(GamepadButton button) { Gamepad current = Gamepad.current; if (current == null) { return null; } return (ButtonControl)(button switch { GamepadButton.DPadUp => current.dpad.up, GamepadButton.DPadDown => current.dpad.down, GamepadButton.DPadLeft => current.dpad.left, GamepadButton.DPadRight => current.dpad.right, GamepadButton.ButtonSouth => current.buttonSouth, GamepadButton.ButtonEast => current.buttonEast, GamepadButton.ButtonWest => current.buttonWest, GamepadButton.ButtonNorth => current.buttonNorth, GamepadButton.LeftShoulder => current.leftShoulder, GamepadButton.RightShoulder => current.rightShoulder, GamepadButton.LeftTrigger => current.leftTrigger, GamepadButton.RightTrigger => current.rightTrigger, GamepadButton.LeftStickButton => current.leftStickButton, GamepadButton.RightStickButton => current.rightStickButton, GamepadButton.Start => current.startButton, GamepadButton.Select => current.selectButton, _ => null, }); } } internal static class KeyNames { public const string Unbound = "-"; public static string Format(KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0) { return "-"; } IEnumerable<string> values = ((KeyboardShortcut)(ref shortcut)).Modifiers.Select(Friendly).Concat(new string[1] { Friendly(((KeyboardShortcut)(ref shortcut)).MainKey) }); return string.Join(" + ", values); } public unsafe static string Friendly(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected I4, but got Unknown //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0036: 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_005a: Expected I4, but got Unknown //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected I4, but got Unknown if ((int)key <= 96) { if ((int)key == 13) { return "Enter"; } if ((int)key == 96) { return "`"; } } else { switch (key - 273) { case 0: return "Up"; case 1: return "Down"; case 3: return "Left"; case 2: return "Right"; } switch (key - 303) { case 3: return "Ctrl"; case 2: return "Right Ctrl"; case 1: return "Shift"; case 0: return "Right Shift"; case 5: return "Alt"; case 4: return "Right Alt"; } switch (key - 323) { case 0: return "Left Mouse"; case 1: return "Right Mouse"; case 2: return "Middle Mouse"; case 3: return "Mouse 4"; case 4: return "Mouse 5"; case 5: return "Mouse 6"; case 6: return "Mouse 7"; } } string text = ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString(); if (text.StartsWith("Alpha")) { return text.Substring("Alpha".Length); } if (text.StartsWith("Keypad")) { return "Num " + text.Substring("Keypad".Length); } return Regex.Replace(text, "(?<=[a-z0-9])(?=[A-Z])", " "); } } internal abstract class KeySource { public abstract string Id { get; } public abstract object Entry { get; } public abstract bool AllowsModifiers { get; } public abstract bool IsDown(); public abstract bool IsPressed(); public abstract bool IsUp(); public abstract string Display(); public abstract string ConflictKey(); public abstract void Set(KeyCode key, IReadOnlyList<KeyCode> modifiers); public abstract void ResetToDefault(); public abstract object Snapshot(); public abstract void Restore(object snapshot); } internal sealed class ShortcutSource : KeySource { private readonly ConfigEntry<KeyboardShortcut> _entry; public override string Id => ((ConfigEntryBase)_entry).Definition.Section + "." + ((ConfigEntryBase)_entry).Definition.Key; public override object Entry => _entry; public override bool AllowsModifiers => true; public ShortcutSource(ConfigEntry<KeyboardShortcut> entry) { _entry = entry; } public override bool IsDown() { //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) KeyboardShortcut value = _entry.Value; return ((KeyboardShortcut)(ref value)).IsDown(); } public override bool IsPressed() { //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) KeyboardShortcut value = _entry.Value; return ((KeyboardShortcut)(ref value)).IsPressed(); } public override bool IsUp() { //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) KeyboardShortcut value = _entry.Value; return ((KeyboardShortcut)(ref value)).IsUp(); } public override string Display() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return KeyNames.Format(_entry.Value); } public unsafe override string ConflictKey() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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) KeyboardShortcut value = _entry.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey == 0) { return ""; } return string.Join("+", (from m in ((KeyboardShortcut)(ref value)).Modifiers select ((object)(*(KeyCode*)(&m))/*cast due to .constrained prefix*/).ToString() into m orderby m select m).Concat(new string[1] { ((object)((KeyboardShortcut)(ref value)).MainKey/*cast due to .constrained prefix*/).ToString() })); } public override void Set(KeyCode key, IReadOnlyList<KeyCode> modifiers) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) _entry.Value = new KeyboardShortcut(key, modifiers.ToArray()); } public override void ResetToDefault() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) _entry.Value = (KeyboardShortcut)((ConfigEntryBase)_entry).DefaultValue; } public override object Snapshot() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return _entry.Value; } public override void Restore(object snapshot) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) _entry.Value = (KeyboardShortcut)snapshot; } } internal sealed class KeyCodeSource : KeySource { private readonly ConfigEntry<KeyCode> _entry; public override string Id => ((ConfigEntryBase)_entry).Definition.Section + "." + ((ConfigEntryBase)_entry).Definition.Key; public override object Entry => _entry; public override bool AllowsModifiers => false; public KeyCodeSource(ConfigEntry<KeyCode> entry) { _entry = entry; } public override bool IsDown() { //IL_0006: 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) if ((int)_entry.Value != 0) { return Input.GetKeyDown(_entry.Value); } return false; } public override bool IsPressed() { //IL_0006: 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) if ((int)_entry.Value != 0) { return Input.GetKey(_entry.Value); } return false; } public override bool IsUp() { //IL_0006: 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) if ((int)_entry.Value != 0) { return Input.GetKeyUp(_entry.Value); } return false; } public override string Display() { //IL_0006: 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) if ((int)_entry.Value != 0) { return KeyNames.Friendly(_entry.Value); } return "-"; } public override string ConflictKey() { //IL_0006: 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_0018: Unknown result type (might be due to invalid IL or missing references) if ((int)_entry.Value != 0) { return ((object)_entry.Value/*cast due to .constrained prefix*/).ToString(); } return ""; } public override void Set(KeyCode key, IReadOnlyList<KeyCode> modifiers) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) _entry.Value = key; } public override void ResetToDefault() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) _entry.Value = (KeyCode)((ConfigEntryBase)_entry).DefaultValue; } public override object Snapshot() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return _entry.Value; } public override void Restore(object snapshot) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) _entry.Value = (KeyCode)snapshot; } } internal sealed class ModSection { public string Guid { get; } public string Name { get; } public List<KeyBinding> Bindings { get; } = new List<KeyBinding>(); public ModSection(string guid, string name) { Guid = guid; Name = (string.IsNullOrWhiteSpace(name) ? guid : name); } } internal static class Registry { private static readonly object Gate = new object(); private static readonly Dictionary<string, ModSection> Sections = new Dictionary<string, ModSection>(); private static readonly List<KeyBinding> Pending = new List<KeyBinding>(); public static ConfigFile Config { get; private set; } public static bool HasAny { get { lock (Gate) { return Sections.Values.Any((ModSection s) => s.Bindings.Count > 0); } } } public static void Initialize(ConfigFile config) { lock (Gate) { Config = config; foreach (KeyBinding item in Pending) { item.BindConfig(config); } Pending.Clear(); } } public static KeyBinding Add(string modGuid, string modName, KeySource source, string label, GamepadButton[] defaultGamepad) { if (string.IsNullOrWhiteSpace(modGuid)) { throw new ArgumentException("modGuid is required", "modGuid"); } if (string.IsNullOrWhiteSpace(label)) { throw new ArgumentException("label is required", "label"); } lock (Gate) { if (!Sections.TryGetValue(modGuid, out var value)) { value = (Sections[modGuid] = new ModSection(modGuid, modName)); } KeyBinding keyBinding = value.Bindings.FirstOrDefault((KeyBinding b) => b.Source.Entry == source.Entry); if (keyBinding != null) { return keyBinding; } KeyBinding keyBinding2 = new KeyBinding(modGuid, value.Name, label, source, defaultGamepad); value.Bindings.Add(keyBinding2); if (Config != null) { keyBinding2.BindConfig(Config); } else { Pending.Add(keyBinding2); } return keyBinding2; } } public static List<ModSection> Snapshot() { lock (Gate) { return Sections.Values.Where((ModSection s) => s.Bindings.Count > 0).OrderBy<ModSection, string>((ModSection s) => s.Name, StringComparer.OrdinalIgnoreCase).ToList(); } } public static string ConfigKey(string modGuid, string id) { string text = modGuid + "." + id; char[] array = new char[7] { '=', '\n', '\t', '"', '\'', '[', ']' }; foreach (char oldChar in array) { text = text.Replace(oldChar, '_'); } return text; } } [BepInPlugin("nathan.qol.keybindings", "Nathans Key Bindings", "0.2.2")] public class KeyBindingsPlugin : BaseUnityPlugin { public const string PluginGuid = "nathan.qol.keybindings"; public const string PluginName = "Nathans Key Bindings"; public const string PluginVersion = "0.2.2"; internal static ManualLogSource Log; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<string> ControllerLayout; private void Awake() { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Shows the Key Bindings tab in the game settings. Mods can still register their keys when it is off."); ControllerLayout = ((BaseUnityPlugin)this).Config.Bind<string>("General", "ControllerLayout", "Auto", new ConfigDescription("Button names shown for the controller. Auto uses the controller type the game detects; set it by hand if Steam Input makes your controller look like an Xbox controller.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[4] { "Auto", "Xbox", "PlayStation", "Nintendo" }), Array.Empty<object>())); Registry.Initialize(((BaseUnityPlugin)this).Config); new Harmony("nathan.qol.keybindings").PatchAll(); Log.LogInfo((object)string.Format("{0} {1} loaded (API version {2})", "Nathans Key Bindings", "0.2.2", 2)); } } internal sealed class KeyBindingsTab : MonoBehaviour, ISettingsTab { private enum CaptureKind { None, Keyboard, Gamepad } private sealed class Row { public KeyBinding Binding; public TMP_Text Label; public TMP_Text KeyboardText; public TMP_Text GamepadText; } private sealed class Original { public object Key; public GamepadButton[] Gamepad; } private sealed class RightClickRelay : MonoBehaviour, IPointerClickHandler, IEventSystemHandler { public Action Action; public void OnPointerClick(PointerEventData eventData) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)eventData.button == 1) { Action?.Invoke(); } } } private const float KeyColumnWidth = 230f; private const float RowHeight = 38f; private static readonly Color Gold = new Color(1f, 0.72f, 0.23f); private static readonly Color Conflict = new Color(1f, 0.38f, 0.32f); private static readonly KeyCode[] Modifiers; private static readonly KeyCode[] CaptureKeys; private readonly List<Row> _rows = new List<Row>(); private readonly Dictionary<KeyBinding, Original> _originals = new Dictionary<KeyBinding, Original>(); private Button _buttonTemplate; private TMP_Text _textTemplate; private Color _buttonTextColor = Color.white; private RectTransform _content; private GameObject _overlay; private TMP_Text _overlayText; private GameObject _firstButton; private CaptureKind _capture; private KeyBinding _target; private float _ignoreInputUntil; private KeyCode _pendingModifier; private readonly List<GamepadButton> _capturedPad = new List<GamepadButton>(); private readonly List<GamepadButton> _ignoredPad = new List<GamepadButton>(); public event Action<string, int> SharedSettingChanged; public void Configure(Button buttonTemplate, TMP_Text textTemplate) { //IL_0021: 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) _buttonTemplate = buttonTemplate; _textTemplate = textTemplate; TMP_Text componentInChildren = ((Component)buttonTemplate).GetComponentInChildren<TMP_Text>(true); if ((Object)(object)componentInChildren != (Object)null) { _buttonTextColor = ((Graphic)componentInChildren).color; } } public void Initialize() { KeyBindingsPlugin.Log.LogInfo((object)("Controller: " + GamepadInput.Describe())); BuildPage(); RefreshAll(); foreach (Row row in _rows) { _originals[row.Binding] = new Original { Key = row.Binding.Source.Snapshot(), Gamepad = row.Binding.GamepadButtons.ToArray() }; } } public void OnTabOpen(Button backButton, Button okButton) { if ((Object)(object)_firstButton != (Object)null && (Object)(object)EventSystem.current != (Object)null && ZInput.IsGamepadActive()) { EventSystem.current.SetSelectedGameObject(_firstButton); } } public void OnBack() { foreach (KeyValuePair<KeyBinding, Original> original in _originals) { original.Key.Source.Restore(original.Value.Key); original.Key.SetGamepadChord(original.Value.Gamepad); } } public void OnOkAsync(OkActionCompletedHandler okActionCompletedCallback) { if (okActionCompletedCallback != null) { okActionCompletedCallback.Invoke(); } } public void OnSharedSettingChanged(string setting, int value) { } public void Terminate() { if (_capture != CaptureKind.None) { _capture = CaptureKind.None; if ((Object)(object)Settings.instance != (Object)null) { Settings.instance.BlockNavigation(false); } } } private void BuildPage() { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: 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_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Expected O, but got Unknown RectTransform val = NewRect("Scroll", ((Component)this).transform, typeof(ScrollRect)); Stretch(val); RectTransform val2 = NewRect("Viewport", (Transform)(object)val, typeof(RectMask2D), typeof(Image)); Stretch(val2); ((Graphic)((Component)val2).GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0f); _content = NewRect("Content", (Transform)(object)val2, typeof(VerticalLayoutGroup), typeof(ContentSizeFitter)); _content.anchorMin = new Vector2(0f, 1f); _content.anchorMax = new Vector2(1f, 1f); _content.pivot = new Vector2(0.5f, 1f); _content.anchoredPosition = Vector2.zero; _content.sizeDelta = Vector2.zero; VerticalLayoutGroup component = ((Component)_content).GetComponent<VerticalLayoutGroup>(); ((LayoutGroup)component).padding = new RectOffset(24, 24, 12, 12); ((HorizontalOrVerticalLayoutGroup)component).spacing = 6f; ((LayoutGroup)component).childAlignment = (TextAnchor)0; ((HorizontalOrVerticalLayoutGroup)component).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)component).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = false; ((Component)_content).GetComponent<ContentSizeFitter>().verticalFit = (FitMode)2; ScrollRect component2 = ((Component)val).GetComponent<ScrollRect>(); component2.viewport = val2; component2.content = _content; component2.horizontal = false; component2.vertical = true; component2.movementType = (MovementType)2; component2.scrollSensitivity = 40f; component2.inertia = false; ((Component)val).gameObject.AddComponent<ScrollRectEnsureVisible>(); AddColumnTitles(); foreach (ModSection item in Registry.Snapshot()) { AddSectionHeader(item); foreach (KeyBinding binding in item.Bindings) { AddRow(binding); } } BuildOverlay(); } private void AddColumnTitles() { //IL_0018: 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) //IL_008c: Unknown result type (might be due to invalid IL or missing references) RectTransform parent = NewRow("Columns"); AddLayout(((Component)AddText((Transform)(object)parent, "Action", (TextAlignmentOptions)4097, Gold)).gameObject, 1f, 260f); AddLayout(((Component)AddText((Transform)(object)parent, "Keyboard / Mouse", (TextAlignmentOptions)4098, Gold)).gameObject, -1f, 230f, 230f); AddLayout(((Component)AddText((Transform)(object)parent, "Controller", (TextAlignmentOptions)4098, Gold)).gameObject, -1f, 230f, 230f); } private void AddSectionHeader(ModSection section) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) RectTransform val = NewRow(section.Name); ((Component)val).GetComponent<LayoutElement>().minHeight = 52f; ((Component)val).GetComponent<LayoutElement>().preferredHeight = 52f; ((LayoutGroup)((Component)val).GetComponent<HorizontalLayoutGroup>()).padding = new RectOffset(0, 0, 12, 0); TMP_Text obj = AddText((Transform)(object)val, section.Name, (TextAlignmentOptions)4097, Gold); obj.fontSize *= 1.25f; AddLayout(((Component)obj).gameObject, 1f, 260f); ((Object)AddButton((Transform)(object)val, "Reset to default", 230f, 32f, delegate { ResetSection(section); }, null)).name = "Reset"; } private void AddRow(KeyBinding binding) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) RectTransform parent = NewRow(binding.Label); TMP_Text val = AddText((Transform)(object)parent, binding.Label, (TextAlignmentOptions)4097, ((Graphic)_textTemplate).color); AddLayout(((Component)val).gameObject, 1f, 260f); GameObject val2 = AddButton((Transform)(object)parent, "", 230f, 34f, delegate { BeginCapture(binding, CaptureKind.Keyboard); }, null); GameObject val3 = AddButton((Transform)(object)parent, "", 230f, 34f, delegate { BeginCapture(binding, CaptureKind.Gamepad); }, delegate { ClearGamepad(binding); }); if ((Object)(object)_firstButton == (Object)null) { _firstButton = val2; } _rows.Add(new Row { Binding = binding, Label = val, KeyboardText = val2.GetComponentInChildren<TMP_Text>(true), GamepadText = val3.GetComponentInChildren<TMP_Text>(true) }); } private RectTransform NewRow(string name) { RectTransform obj = NewRect(name, (Transform)(object)_content, typeof(HorizontalLayoutGroup), typeof(LayoutElement)); HorizontalLayoutGroup component = ((Component)obj).GetComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)component).spacing = 12f; ((LayoutGroup)component).childAlignment = (TextAnchor)3; ((HorizontalOrVerticalLayoutGroup)component).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)component).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)component).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)component).childForceExpandHeight = true; LayoutElement component2 = ((Component)obj).GetComponent<LayoutElement>(); component2.minHeight = 38f; component2.preferredHeight = 38f; return obj; } private TMP_Text AddText(Transform parent, string text, TextAlignmentOptions alignment, Color color) { //IL_0030: 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) GameObject obj = Object.Instantiate<GameObject>(((Component)_textTemplate).gameObject, parent); ((Object)obj).name = "Text"; obj.SetActive(true); TMP_Text component = obj.GetComponent<TMP_Text>(); component.text = text; component.alignment = alignment; ((Graphic)component).color = color; ((Graphic)component).raycastTarget = false; component.textWrappingMode = (TextWrappingModes)0; component.overflowMode = (TextOverflowModes)1; return component; } private GameObject AddButton(Transform parent, string text, float width, float height, Action onClick, Action onRightClick) { //IL_003b: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown GameObject val = Object.Instantiate<GameObject>(((Component)_buttonTemplate).gameObject, parent); ((Object)val).name = "Button"; val.SetActive(true); Button component = val.GetComponent<Button>(); Navigation navigation = default(Navigation); ((Navigation)(ref navigation)).mode = (Mode)3; ((Selectable)component).navigation = navigation; component.onClick = new ButtonClickedEvent(); ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { onClick(); }); AddLayout(val, -1f, width, width, height, height); TMP_Text componentInChildren = val.GetComponentInChildren<TMP_Text>(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.text = text; componentInChildren.enableAutoSizing = true; componentInChildren.fontSizeMin = 12f; componentInChildren.fontSizeMax = componentInChildren.fontSize; } if (onRightClick != null) { val.AddComponent<RightClickRelay>().Action = onRightClick; } return val; } private static LayoutElement AddLayout(GameObject go, float flexibleWidth = -1f, float minWidth = -1f, float preferredWidth = -1f, float minHeight = -1f, float preferredHeight = -1f) { LayoutElement obj = go.GetComponent<LayoutElement>() ?? go.AddComponent<LayoutElement>(); obj.flexibleWidth = flexibleWidth; obj.minWidth = minWidth; obj.preferredWidth = preferredWidth; obj.minHeight = minHeight; obj.preferredHeight = preferredHeight; return obj; } private static RectTransform NewRect(string name, Transform parent, params Type[] components) { //IL_001f: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown RectTransform val = (RectTransform)new GameObject(name, new Type[1] { typeof(RectTransform) }.Concat(components).ToArray()).transform; ((Transform)val).SetParent(parent, false); return val; } private static void Stretch(RectTransform rect) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) rect.anchorMin = Vector2.zero; rect.anchorMax = Vector2.one; rect.offsetMin = Vector2.zero; rect.offsetMax = Vector2.zero; } private void BuildOverlay() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: 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_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: 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_00bb: Unknown result type (might be due to invalid IL or missing references) RectTransform val = NewRect("CaptureOverlay", ((Component)this).transform, typeof(Image)); Stretch(val); ((Graphic)((Component)val).GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.85f); _overlay = ((Component)val).gameObject; _overlayText = AddText((Transform)(object)val, "", (TextAlignmentOptions)514, Color.white); RectTransform val2 = (RectTransform)_overlayText.transform; val2.anchorMin = new Vector2(0.1f, 0.3f); val2.anchorMax = new Vector2(0.9f, 0.7f); val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; _overlayText.textWrappingMode = (TextWrappingModes)1; _overlayText.overflowMode = (TextOverflowModes)0; TMP_Text overlayText = _overlayText; overlayText.fontSize *= 1.3f; _overlay.SetActive(false); } private void RefreshAll() { //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, int> dictionary = (from r in _rows select r.Binding.Source.ConflictKey() into k where k.Length > 0 group k by k).ToDictionary((IGrouping<string, string> g) => g.Key, (IGrouping<string, string> g) => g.Count()); Dictionary<string, int> dictionary2 = (from r in _rows select ChordText.Format(r.Binding.GamepadButtons) into c where c != "None" group c by c).ToDictionary((IGrouping<string, string> g) => g.Key, (IGrouping<string, string> g) => g.Count()); foreach (Row row in _rows) { string text = row.Binding.Source.ConflictKey(); bool flag = text.Length > 0 && dictionary[text] > 1; row.KeyboardText.text = row.Binding.Source.Display(); ((Graphic)row.KeyboardText).color = (flag ? Conflict : _buttonTextColor); string text2 = ChordText.Format(row.Binding.GamepadButtons); bool flag2 = text2 != "None" && dictionary2[text2] > 1; row.GamepadText.text = GamepadInput.Name(row.Binding.GamepadButtons); ((Graphic)row.GamepadText).color = (flag2 ? Conflict : _buttonTextColor); ((Graphic)row.Label).color = ((flag || flag2) ? Conflict : ((Graphic)_textTemplate).color); } } private void ResetSection(ModSection section) { foreach (KeyBinding binding in section.Bindings) { binding.Source.ResetToDefault(); binding.SetGamepadChord(binding.DefaultGamepadButtons); binding.NotifyChanged(); } RefreshAll(); } private void ClearGamepad(KeyBinding binding) { binding.SetGamepad(GamepadButton.None); binding.NotifyChanged(); RefreshAll(); } private void BeginCapture(KeyBinding binding, CaptureKind kind) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (_capture == CaptureKind.None) { _capture = kind; _target = binding; _pendingModifier = (KeyCode)0; _capturedPad.Clear(); _ignoredPad.Clear(); _ignoredPad.AddRange(GamepadInput.HeldNow()); _ignoreInputUntil = Time.unscaledTime + 0.25f; string text = ((kind == CaptureKind.Keyboard) ? "Press the new key or mouse button for" : "Press the new controller button for"); string text2 = ((kind == CaptureKind.Keyboard) ? "Hold Ctrl, Shift or Alt first for a combination (also with the left mouse button). Esc: cancel" : ((Gamepad.current == null) ? "No controller found. Esc: cancel" : "Hold up to three buttons together, then let go. Esc: cancel (right-click a controller button to clear it)")); _overlayText.text = text + "\n<color=#FFB83B>" + binding.Label + "</color>\n\n<size=70%>" + text2 + "</size>"; _overlay.SetActive(true); if ((Object)(object)Settings.instance != (Object)null) { Settings.instance.BlockNavigation(true); } } } private void Update() { if (_capture != CaptureKind.None && !(Time.unscaledTime < _ignoreInputUntil)) { if (Input.GetKeyDown((KeyCode)27)) { EndCapture(); } else if (_capture == CaptureKind.Keyboard) { PollKeyboard(); } else { PollGamepad(); } } } private void PollKeyboard() { //IL_000d: 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_0017: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) KeyCode[] captureKeys = CaptureKeys; foreach (KeyCode val in captureKeys) { if (Input.GetKeyDown(val)) { Apply(val, HeldModifiers()); return; } } if (Input.GetKeyDown((KeyCode)323) && _target.Source.AllowsModifiers && HeldModifiers().Length != 0) { Apply((KeyCode)323, HeldModifiers()); return; } captureKeys = Modifiers; foreach (KeyCode val2 in captureKeys) { if (Input.GetKeyDown(val2)) { _pendingModifier = val2; } } if ((int)_pendingModifier != 0 && Input.GetKeyUp(_pendingModifier)) { Apply(_pendingModifier, Array.Empty<KeyCode>()); } } private void PollGamepad() { List<GamepadButton> held = GamepadInput.HeldNow(); _ignoredPad.RemoveAll((GamepadButton b) => !held.Contains(b)); foreach (GamepadButton item in held) { if (!_ignoredPad.Contains(item) && !_capturedPad.Contains(item) && _capturedPad.Count < 3) { _capturedPad.Add(item); } } if (_capturedPad.Count != 0) { if (held.Count > _ignoredPad.Count) { ShowCaptured(); return; } _target.SetGamepadChord(_capturedPad.ToArray()); Finish(); } } private void ShowCaptured() { _overlayText.text = "Press the new controller button for\n<color=#FFB83B>" + _target.Label + "</color>\n\n<size=130%>" + GamepadInput.Name(_capturedPad) + "</size>\n\n<size=70%>Let go of all buttons to confirm. Esc: cancel</size>"; } private static KeyCode[] HeldModifiers() { return ((IEnumerable<KeyCode>)Modifiers).Where((Func<KeyCode, bool>)Input.GetKey).ToArray(); } private void Apply(KeyCode key, IReadOnlyList<KeyCode> modifiers) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) KeySource source = _target.Source; IReadOnlyList<KeyCode> modifiers2; if (!_target.Source.AllowsModifiers) { IReadOnlyList<KeyCode> readOnlyList = Array.Empty<KeyCode>(); modifiers2 = readOnlyList; } else { modifiers2 = modifiers; } source.Set(key, modifiers2); Finish(); } private void Finish() { _target.NotifyChanged(); RefreshAll(); EndCapture(); } private void EndCapture() { _capture = CaptureKind.None; _overlay.SetActive(false); if (((Behaviour)this).isActiveAndEnabled) { ((MonoBehaviour)this).StartCoroutine(UnblockNavigation()); } else if ((Object)(object)Settings.instance != (Object)null) { Settings.instance.BlockNavigation(false); } } private IEnumerator UnblockNavigation() { yield return null; if (_capture == CaptureKind.None && (Object)(object)Settings.instance != (Object)null) { Settings.instance.BlockNavigation(false); } } static KeyBindingsTab() { //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_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) KeyCode[] array = new KeyCode[6]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); Modifiers = (KeyCode[])(object)array; CaptureKeys = (from k in ((KeyCode[])Enum.GetValues(typeof(KeyCode))).Distinct() where (int)k != 0 && (int)k != 27 && (int)k != 323 where (int)k < 330 || (int)k > 509 where !Modifiers.Contains(k) where (int)k != 310 && (int)k != 309 && (int)k != 311 && (int)k != 312 select k).ToArray(); } } [HarmonyPatch(typeof(Settings), "InitializeTabs")] internal static class InitializeTabsPatch { private static bool _dumped; private static void Prefix(Settings __instance) { try { Install(__instance); } catch (Exception arg) { KeyBindingsPlugin.Log.LogError((object)$"Could not add the Key Bindings tab: {arg}"); } } private static void Install(Settings settings) { //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Expected O, but got Unknown //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Expected O, but got Unknown //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Expected O, but got Unknown //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Expected O, but got Unknown //IL_0370: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_037d: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_038d: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Expected O, but got Unknown //IL_039c: Expected O, but got Unknown //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_0360: Unknown result type (might be due to invalid IL or missing references) if (!KeyBindingsPlugin.Enabled.Value || !Registry.HasAny) { return; } TabHandler componentInChildren = ((Component)settings).GetComponentInChildren<TabHandler>(); KeyboardMouseSettings componentInChildren2 = ((Component)settings).GetComponentInChildren<KeyboardMouseSettings>(true); if ((Object)(object)componentInChildren == (Object)null || (Object)(object)componentInChildren2 == (Object)null) { KeyBindingsPlugin.Log.LogWarning((object)"The settings screen looks different than expected, no Key Bindings tab added"); return; } Tab val = ((IEnumerable<Tab>)componentInChildren.m_tabs).LastOrDefault((Func<Tab, bool>)((Tab t) => (Object)(object)t.m_button != (Object)null && (Object)(object)t.m_page != (Object)null)); if (val == null) { KeyBindingsPlugin.Log.LogWarning((object)"No existing settings tab found to copy, no Key Bindings tab added"); return; } RectTransform val2 = ((componentInChildren2.m_keys.Count > 0) ? componentInChildren2.m_keys[0].m_keyTransform : null); Button val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponentInChildren<Button>(true) : null); if ((Object)(object)val3 == (Object)null || (Object)(object)componentInChildren2.m_mouseSensitivityText == (Object)null) { KeyBindingsPlugin.Log.LogWarning((object)"Could not find the key button style of the game, no Key Bindings tab added"); return; } if (!_dumped) { _dumped = true; KeyBindingsPlugin.Log.LogInfo((object)("Settings tab bar:\n" + UiDump.Describe(((Component)val.m_button).transform.parent, 2))); KeyBindingsPlugin.Log.LogInfo((object)("Settings page (template):\n" + UiDump.Describe((Transform)(object)val.m_page, 2))); KeyBindingsPlugin.Log.LogInfo((object)("Key button (template):\n" + UiDump.Describe(((Component)val3).transform, 3))); } GameObject val4 = new GameObject("NathansKeyBindingsPage", new Type[1] { typeof(RectTransform) }); RectTransform val5 = (RectTransform)val4.transform; ((Transform)val5).SetParent(((Transform)val.m_page).parent, false); val5.anchorMin = val.m_page.anchorMin; val5.anchorMax = val.m_page.anchorMax; val5.pivot = val.m_page.pivot; val5.anchoredPosition = val.m_page.anchoredPosition; val5.sizeDelta = val.m_page.sizeDelta; val4.SetActive(false); val4.AddComponent<KeyBindingsTab>().Configure(val3, componentInChildren2.m_mouseSensitivityText); GameObject obj = Object.Instantiate<GameObject>(((Component)val.m_button).gameObject, ((Component)val.m_button).transform.parent); ((Object)obj).name = "NathansKeyBindingsTab"; Button component = obj.GetComponent<Button>(); component.onClick = new ButtonClickedEvent(); RectTransform val6 = (RectTransform)obj.transform; RectTransform val7 = (RectTransform)((Component)val.m_button).transform; TMP_Text[] componentsInChildren = obj.GetComponentsInChildren<TMP_Text>(true); foreach (TMP_Text val8 in componentsInChildren) { if (!IsInside(val8.transform, "KeyHint", (Transform)(object)val6)) { val8.text = "Key Bindings"; } } Transform val9 = ((Transform)val7).Find("KeyHint"); Transform val10 = ((Transform)val6).Find("KeyHint"); if ((Object)(object)val9 != (Object)null && (Object)(object)val10 != (Object)null) { ((Component)val9).gameObject.SetActive(false); GameObject[] tabKeyHints = settings.m_tabKeyHints; for (int num2 = 0; num2 < tabKeyHints.Length; num2++) { if ((Object)(object)tabKeyHints[num2] == (Object)(object)((Component)val9).gameObject) { tabKeyHints[num2] = ((Component)val10).gameObject; } } } if ((Object)(object)((Component)((Transform)val6).parent).GetComponent<LayoutGroup>() == (Object)null) { Vector2 anchoredPosition = val7.anchoredPosition; Rect rect = val7.rect; val6.anchoredPosition = anchoredPosition + new Vector2(((Rect)(ref rect)).width + 8f, 0f); } componentInChildren.m_tabs.Add(new Tab { m_button = component, m_page = val5, m_default = false, m_onClick = new UnityEvent() }); } private static bool IsInside(Transform child, string ancestorName, Transform root) { Transform val = child; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root) { if (((Object)val).name == ancestorName) { return true; } val = val.parent; } return false; } } internal static class UiDump { public static string Describe(Transform root, int maxDepth) { StringBuilder stringBuilder = new StringBuilder(); Append(stringBuilder, root, 0, maxDepth); return stringBuilder.ToString(); } private static void Append(StringBuilder sb, Transform t, int depth, int maxDepth) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Expected O, but got Unknown sb.Append(new string(' ', depth * 2)).Append(((Object)t).name).Append(((Component)t).gameObject.activeSelf ? "" : " (inactive)"); RectTransform val = (RectTransform)(object)((t is RectTransform) ? t : null); if (val != null) { object[] obj = new object[4] { val.anchorMin, val.anchorMax, val.anchoredPosition, null }; Rect rect = val.rect; obj[3] = ((Rect)(ref rect)).size; sb.Append(string.Format(" anchors={0}-{1} pos={2} size={3}", obj)); } sb.Append(" [").Append(string.Join(",", (from c in ((Component)t).GetComponents<Component>() where (Object)(object)c != (Object)null select ((object)c).GetType().Name).ToArray())).Append("]\n"); if (depth >= maxDepth) { return; } foreach (Transform item in t) { Transform t2 = item; Append(sb, t2, depth + 1, maxDepth); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }