using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using KeybindLib.Classes;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("KeybindLib")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("KeybindLib")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("a435cffd-1c69-437a-9daa-52fd5a9b02e6")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace KeybindLib
{
[BepInPlugin("bulletbot.keybindlib", "KeybindLib", "1.0.3")]
internal class Plugin : BaseUnityPlugin
{
private const string modGUID = "bulletbot.keybindlib";
private const string modName = "KeybindLib";
private const string modVer = "1.0.3";
internal static Plugin instance;
internal ManualLogSource logger;
private readonly Harmony harmony = new Harmony("bulletbot.keybindlib");
private bool hasPatched;
internal List<Keybind> registeredKeybinds;
private void Awake()
{
instance = this;
logger = Logger.CreateLogSource("KeybindLib");
registeredKeybinds = new List<Keybind>();
logger.LogMessage((object)"KeybindLib has started.");
SceneManager.activeSceneChanged += delegate
{
if (!hasPatched)
{
harmony.PatchAll();
logger.LogMessage((object)$"{registeredKeybinds.Count} keybind(s) has been initialized.");
hasPatched = true;
}
};
}
}
}
namespace KeybindLib.Patches
{
[HarmonyPatch(typeof(MenuManager))]
internal class MenuManagerPatch
{
private static readonly float _headerOffset = 30f;
private static readonly float _categoryOffset = 26.5f;
private static readonly float _categoryHeaderOffset = 6.5f;
private static readonly float _buttonOffset = 42f;
private static readonly float _buttonHeaderOffset = 15f;
private static readonly float _buttonCategoryOffset = 11.5f;
private static readonly float _buttonBoolSettingOffset = 27.25f;
private static readonly float _buttonBoolSettingHeaderOffset = 12.5f;
private static readonly float _buttonBoolSettingCategoryOffset = 9f;
private static readonly float _boolSettingOffset = 32.25f;
private static readonly float _boolSettingHeaderOffset = 15.25f;
private static readonly float _boolSettingCategoryOffset = 20.25f;
[HarmonyPatch("Start")]
[HarmonyPrefix]
private static void Start(ref List<MenuPages> ___menuPages)
{
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Expected O, but got Unknown
//IL_015b: Unknown result type (might be due to invalid IL or missing references)
//IL_0160: Unknown result type (might be due to invalid IL or missing references)
//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
//IL_0254: Unknown result type (might be due to invalid IL or missing references)
//IL_025d: Unknown result type (might be due to invalid IL or missing references)
//IL_0264: Unknown result type (might be due to invalid IL or missing references)
//IL_030e: Unknown result type (might be due to invalid IL or missing references)
//IL_0317: Unknown result type (might be due to invalid IL or missing references)
//IL_031e: Unknown result type (might be due to invalid IL or missing references)
//IL_05a1: Unknown result type (might be due to invalid IL or missing references)
//IL_05a6: Unknown result type (might be due to invalid IL or missing references)
//IL_05f0: Unknown result type (might be due to invalid IL or missing references)
//IL_05f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0600: Unknown result type (might be due to invalid IL or missing references)
//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
//IL_040b: Unknown result type (might be due to invalid IL or missing references)
//IL_0414: Unknown result type (might be due to invalid IL or missing references)
//IL_041b: Unknown result type (might be due to invalid IL or missing references)
//IL_0476: Unknown result type (might be due to invalid IL or missing references)
//IL_047b: Unknown result type (might be due to invalid IL or missing references)
//IL_04c5: Unknown result type (might be due to invalid IL or missing references)
//IL_04ce: Unknown result type (might be due to invalid IL or missing references)
//IL_04d5: Unknown result type (might be due to invalid IL or missing references)
if (Plugin.instance.registeredKeybinds.Count <= 0)
{
return;
}
MenuPages val = ((IEnumerable<MenuPages>)___menuPages).FirstOrDefault((Func<MenuPages, bool>)((MenuPages x) => (int)x.menuPageIndex == 6));
Transform child = val.menuPage.transform.GetChild(3);
MenuScrollBox component = ((Component)child).GetComponent<MenuScrollBox>();
Transform child2 = child.GetChild(1).GetChild(0);
GameObject gameObject = ((Component)child2.Find("Header Expressions")).gameObject;
Vector3 localPosition = gameObject.transform.localPosition;
GameObject gameObject2 = ((Component)child2.Find("Header Grabbing")).gameObject;
Vector3 localPosition2 = gameObject2.transform.localPosition;
GameObject gameObject3 = ((Component)child2.Find("Big Button Map")).gameObject;
Vector3 localPosition3 = gameObject3.transform.localPosition;
GameObject gameObject4 = ((Component)child2.Find("Bool Setting - ")).gameObject;
Vector3 localPosition4 = gameObject4.transform.localPosition;
GameObject val2 = null;
foreach (Transform item in child2)
{
Transform val3 = item;
if (((Object)val3).name == "Bool Setting - ")
{
val2 = ((Component)val3).gameObject;
}
}
Vector3 localPosition5 = val2.transform.localPosition;
List<string> currentHeaders = new List<string>();
List<(string, string)> currentCategories = new List<(string, string)>();
Plugin.instance.registeredKeybinds.Sort(delegate(Keybind a, Keybind b)
{
int num2 = a.modOrderIndex.CompareTo(b.modOrderIndex);
if (num2 != 0)
{
return num2;
}
bool flag3 = !string.IsNullOrEmpty(a.category);
bool flag4 = !string.IsNullOrEmpty(b.category);
if (flag3 != flag4)
{
return flag3.CompareTo(flag4);
}
bool registeredAsToggle = a.registeredAsToggle;
bool registeredAsToggle2 = b.registeredAsToggle;
return (registeredAsToggle != registeredAsToggle2) ? registeredAsToggle2.CompareTo(registeredAsToggle) : a.registerIndex.CompareTo(b.registerIndex);
});
float num = child2.GetChild(child2.childCount - 1).localPosition.y;
List<Keybind> registeredKeybinds = Plugin.instance.registeredKeybinds;
for (int i = 0; i < registeredKeybinds.Count; i++)
{
Keybind keybind2 = registeredKeybinds[i];
bool flag = RequiresHeader(keybind2);
if (flag)
{
num -= _headerOffset;
GameObject val4 = Object.Instantiate<GameObject>(gameObject);
((Object)val4).name = "Header " + keybind2.modGuid;
((TMP_Text)val4.GetComponentInChildren<TextMeshProUGUI>()).text = keybind2.modGuid;
val4.transform.SetParent(child2);
val4.transform.localPosition = new Vector3(localPosition.x, num, localPosition.z);
currentHeaders.Add(keybind2.modGuid);
}
bool flag2 = RequiresCategory(keybind2);
if (flag2)
{
num -= _categoryOffset;
if (flag)
{
num -= _categoryHeaderOffset;
}
GameObject val5 = Object.Instantiate<GameObject>(gameObject2);
((Object)val5).name = "Category " + keybind2.modGuid + " " + keybind2.category;
((TMP_Text)val5.GetComponentInChildren<TextMeshProUGUI>()).text = keybind2.category;
val5.transform.SetParent(child2);
val5.transform.localPosition = new Vector3(localPosition2.x, num, localPosition2.z);
currentCategories.Add((keybind2.modGuid, keybind2.category));
flag2 = true;
}
if (keybind2.inputAction != null)
{
num -= _buttonOffset;
if (flag)
{
num -= _buttonHeaderOffset;
}
if (flag2)
{
num -= _buttonCategoryOffset;
}
GameObject val6 = Object.Instantiate<GameObject>(gameObject3);
string name = keybind2.inputAction.name;
((Object)val6).name = "Big Button " + keybind2.modGuid + " " + name;
val6.GetComponent<MenuBigButton>().buttonTitle = name;
((TMP_Text)val6.GetComponentInChildren<TextMeshProUGUI>()).text = name;
val6.GetComponent<MenuKeybind>().inputKey = keybind2.inputKey;
val6.transform.SetParent(child2);
val6.transform.localPosition = new Vector3(localPosition3.x, num, localPosition3.z);
if (keybind2.toggle != null)
{
num -= _buttonBoolSettingOffset;
GameObject val7 = Object.Instantiate<GameObject>(gameObject4);
((Object)val7).name = "Button Toggle " + keybind2.modGuid + " " + name;
val7.GetComponent<MenuKeybindToggle>().inputKey = keybind2.inputKey;
MenuTwoOptions component2 = val7.GetComponent<MenuTwoOptions>();
component2.option2Text = keybind2.toggle.falseText;
component2.option1Text = keybind2.toggle.trueText;
val7.transform.SetParent(child2);
val7.transform.localPosition = new Vector3(localPosition4.x, num, localPosition4.z);
}
if (i + 1 < registeredKeybinds.Count)
{
Keybind keybind3 = registeredKeybinds[i + 1];
if (RequiresHeader(keybind3))
{
num -= _buttonBoolSettingHeaderOffset;
}
if (RequiresCategory(keybind3))
{
num -= _buttonBoolSettingCategoryOffset;
}
}
}
else
{
num -= _boolSettingOffset;
if (flag)
{
num -= _boolSettingHeaderOffset;
}
if (flag2)
{
num -= _boolSettingCategoryOffset;
}
GameObject val8 = Object.Instantiate<GameObject>(val2);
((Object)val8).name = "Toggle " + keybind2.modGuid + " " + keybind2.category;
val8.GetComponent<MenuKeybindToggle>().inputKey = keybind2.inputKey;
MenuTwoOptions component3 = val8.GetComponent<MenuTwoOptions>();
component3.option2Text = keybind2.toggle.falseText;
component3.option1Text = keybind2.toggle.trueText;
val8.transform.SetParent(child2);
val8.transform.localPosition = new Vector3(localPosition5.x, num, localPosition5.z);
}
component.heightPadding += 4f;
}
bool RequiresCategory(Keybind keybind)
{
return !string.IsNullOrEmpty(keybind.category) && !currentCategories.Contains((keybind.modGuid, keybind.category));
}
bool RequiresHeader(Keybind keybind)
{
return !currentHeaders.Contains(keybind.modGuid);
}
}
}
[HarmonyPatch(typeof(InputManager))]
internal class InputManagerPatch
{
[HarmonyPatch("Start")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> StartTranspiler(IEnumerable<CodeInstruction> instructions)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Expected O, but got Unknown
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected O, but got Unknown
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Expected O, but got Unknown
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Expected O, but got Unknown
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Expected O, but got Unknown
CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null);
val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
{
new CodeMatch((OpCode?)OpCodes.Ldstr, (object)"DefaultKeyBindings.es3", (string)null)
});
val.Insert((CodeInstruction[])(object)new CodeInstruction[3]
{
new CodeInstruction(OpCodes.Ldarg_0, (object)null),
new CodeInstruction(OpCodes.Ldflda, (object)AccessTools.Field(typeof(InputManager), "tagDictionary")),
new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(InputManagerPatch), "Start", (Type[])null, (Type[])null))
});
return val.InstructionEnumeration();
}
private static void Start(ref Dictionary<string, InputKey> tagDictionary)
{
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
foreach (Keybind registeredKeybind in Plugin.instance.registeredKeybinds)
{
if (!string.IsNullOrEmpty(registeredKeybind.tag))
{
tagDictionary.Add(registeredKeybind.tag, registeredKeybind.inputKey);
}
}
}
[HarmonyPatch("InitializeInputs")]
[HarmonyTranspiler]
private static IEnumerable<CodeInstruction> InitializeInputsTranspiler(IEnumerable<CodeInstruction> instructions)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Expected O, but got Unknown
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Expected O, but got Unknown
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Expected O, but got Unknown
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Expected O, but got Unknown
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Expected O, but got Unknown
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Expected O, but got Unknown
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Expected O, but got Unknown
CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null);
int num = -1;
while (true)
{
val.MatchForward(false, (CodeMatch[])(object)new CodeMatch[1]
{
new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(Dictionary<InputKey, InputAction>), "set_Item", (Type[])null, (Type[])null), (string)null)
});
if (!val.IsValid)
{
break;
}
num = val.Pos;
val.Advance(1);
}
if (num != -1)
{
val.Start();
val.Advance(num + 1);
val.Insert((CodeInstruction[])(object)new CodeInstruction[5]
{
new CodeInstruction(OpCodes.Ldarg_0, (object)null),
new CodeInstruction(OpCodes.Ldflda, (object)AccessTools.Field(typeof(InputManager), "inputActions")),
new CodeInstruction(OpCodes.Ldarg_0, (object)null),
new CodeInstruction(OpCodes.Ldflda, (object)AccessTools.Field(typeof(InputManager), "inputToggle")),
new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(InputManagerPatch), "InitializeInputs", (Type[])null, (Type[])null))
});
}
return val.InstructionEnumeration();
}
private static void InitializeInputs(ref Dictionary<InputKey, InputAction> inputActions, ref Dictionary<InputKey, bool> inputToggle)
{
//IL_002d: 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)
foreach (Keybind registeredKeybind in Plugin.instance.registeredKeybinds)
{
if (registeredKeybind.inputAction != null)
{
inputActions[registeredKeybind.inputKey] = registeredKeybind.inputAction;
}
if (registeredKeybind.toggle != null)
{
inputToggle.Add(registeredKeybind.inputKey, registeredKeybind.toggle.defaultValue);
}
}
}
}
}
namespace KeybindLib.Classes
{
public class Keybind
{
public class Toggle
{
public bool defaultValue;
public string falseText = "hold";
public string trueText = "toggle";
}
internal bool registeredAsToggle;
internal int modOrderIndex;
internal int registerIndex;
public string modGuid { get; internal set; }
public string category { get; internal set; }
public string tag { get; internal set; }
public Toggle toggle { get; internal set; }
public InputKey inputKey { get; internal set; }
public InputAction inputAction { get; internal set; }
}
public static class Keybinds
{
internal static readonly Dictionary<string, int> _modOrder = new Dictionary<string, int>();
internal static int _nextRegisterIndex = 0;
internal static int _nextModOrderIndex = 0;
private static BepInPlugin GetPluginByCallingAssembly(Assembly assembly)
{
BepInPlugin val = (from x in assembly.GetTypes()
select ((MemberInfo)x).GetCustomAttribute<BepInPlugin>()).FirstOrDefault();
if (val == null)
{
val = (from x in assembly.GetExportedTypes()
select ((MemberInfo)x).GetCustomAttribute<BepInPlugin>()).FirstOrDefault();
}
return val;
}
public static Keybind Bind(string name, string binding)
{
return Register(GetPluginByCallingAssembly(Assembly.GetCallingAssembly()), null, name, binding);
}
public static Keybind Bind(string category, string name, string binding)
{
return Register(GetPluginByCallingAssembly(Assembly.GetCallingAssembly()), category, name, binding);
}
public static Keybind Toggle(Keybind.Toggle toggle)
{
return Register(GetPluginByCallingAssembly(Assembly.GetCallingAssembly()), null, null, null, toggle, isToggle: true);
}
public static Keybind Toggle(string category, Keybind.Toggle toggle)
{
return Register(GetPluginByCallingAssembly(Assembly.GetCallingAssembly()), category, null, null, toggle, isToggle: true);
}
public static Keybind Toggle(Keybind keybind, Keybind.Toggle toggle)
{
BepInPlugin val = (from x in Assembly.GetCallingAssembly().GetTypes()
select ((MemberInfo)x).GetCustomAttribute<BepInPlugin>()).FirstOrDefault();
if (val == null)
{
Plugin.instance.logger.LogMessage((object)"Failed to apply toggle because the calling mod could not be identified.");
return null;
}
if (keybind == null)
{
Plugin.instance.logger.LogMessage((object)"Failed to apply toggle because the provided keybind was null.");
return null;
}
bool registeredAsToggle = keybind.registeredAsToggle;
string modGuid = keybind.modGuid;
string category = keybind.category;
string text = ((keybind.inputAction != null) ? keybind.inputAction.name : null);
bool flag = keybind.toggle != null;
if (modGuid == val.GUID && Plugin.instance.registeredKeybinds.Contains(keybind))
{
Plugin.instance.logger.LogMessage((object)(((toggle == null) ? "Removed" : (flag ? "Replaced" : "Attached")) + " toggle" + ((!registeredAsToggle) ? (((toggle == null) ? " from" : " to") + " keybind" + ((!string.IsNullOrEmpty(text)) ? (" \"" + text + "\"") : "")) : "") + ((!string.IsNullOrEmpty(category)) ? (" in category \"" + category + "\"") : "") + " for mod \"" + modGuid + "\"."));
keybind.toggle = toggle;
return keybind;
}
Plugin.instance.logger.LogMessage((object)("Failed to " + ((toggle == null) ? "remove" : (flag ? "replace" : "attach")) + " toggle" + ((!registeredAsToggle) ? (((toggle == null) ? " from" : " to") + " keybind" + ((!string.IsNullOrEmpty(text)) ? (" \"" + text + "\"") : "")) : "") + ((!string.IsNullOrEmpty(keybind.category)) ? (" in category \"" + category + "\"") : "") + " for mod \"" + modGuid + "\"."));
return null;
}
internal static Keybind Register(BepInPlugin plugin, string category = null, string name = null, string binding = null, Keybind.Toggle toggle = null, bool isToggle = false)
{
//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)
//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
//IL_01e6: Expected I4, but got Unknown
//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0207: Expected O, but got Unknown
if (plugin == null)
{
Plugin.instance.logger.LogMessage((object)("Failed to register a " + (isToggle ? "toggle" : "keybind") + " because the calling mod could not be identified."));
return null;
}
string modGuid = plugin.GUID;
InputKey inputKey = ComputeInputKey();
bool flag = !isToggle && (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(binding) || Plugin.instance.registeredKeybinds.Any((Keybind x) => x.modGuid == modGuid && SameCategory(x) && !x.registeredAsToggle && x.inputKey == inputKey));
bool flag2 = isToggle && (toggle == null || Plugin.instance.registeredKeybinds.Any((Keybind x) => x.modGuid == modGuid && SameCategory(x) && x.registeredAsToggle && x.inputKey == inputKey));
if (flag || flag2)
{
Plugin.instance.logger.LogMessage((object)("Failed to register " + (isToggle ? "toggle" : ("keybind" + ((!string.IsNullOrEmpty(name)) ? (" \"" + name + "\"") : ""))) + ((!string.IsNullOrEmpty(category)) ? (" in category \"" + category + "\"") : "") + " for mod \"" + modGuid + "\"."));
return null;
}
Keybind keybind = new Keybind
{
modGuid = modGuid,
category = category,
inputKey = inputKey
};
if (isToggle)
{
keybind.toggle = toggle;
}
else
{
keybind.tag = $"[{(int)inputKey}]";
keybind.inputAction = new InputAction(name, (InputActionType)0, binding, (string)null, (string)null, (string)null);
}
keybind.registeredAsToggle = isToggle;
if (!_modOrder.TryGetValue(modGuid, out var value))
{
value = _nextModOrderIndex++;
_modOrder[modGuid] = value;
}
keybind.modOrderIndex = value;
keybind.registerIndex = _nextRegisterIndex++;
Plugin.instance.registeredKeybinds.Add(keybind);
Plugin.instance.logger.LogMessage((object)("Registered " + (isToggle ? "toggle" : ("keybind \"" + name + "\"")) + ((!string.IsNullOrEmpty(category)) ? (" in category \"" + category + "\"") : "") + " for mod \"" + modGuid + "\"."));
return keybind;
InputKey ComputeInputKey()
{
//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
if (string.IsNullOrEmpty(category))
{
category = string.Empty;
}
if (string.IsNullOrEmpty(name))
{
name = string.Empty;
}
string text = modGuid + "|" + category + "|" + name;
uint num = 2166136261u;
for (int i = 0; i < text.Length; i++)
{
num ^= text[i];
num *= 16777619;
}
num &= 0x3FFFFFFFu;
num |= 0x40000000u;
return (InputKey)num;
}
bool SameCategory(Keybind x)
{
return (string.IsNullOrEmpty(x.category) && string.IsNullOrEmpty(category)) || (!string.IsNullOrEmpty(x.category) && !string.IsNullOrEmpty(category) && x.category.Equals(category, StringComparison.OrdinalIgnoreCase));
}
}
}
}