using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; 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("BetterControls")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("BetterControls")] [assembly: AssemblyTitle("BetterControls")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 DysonSphereProgram.Modding.BetterControls { [BepInPlugin("com.zach.BetterControls", "BetterControls", "0.1.7.0")] [BepInProcess("DSPGAME.exe")] public class Plugin : BaseUnityPlugin { public const string GUID = "com.zach.BetterControls"; public const string NAME = "BetterControls"; public const string VERSION = "0.1.7.0"; private Harmony _harmony; internal static ManualLogSource Log; private void Awake() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; try { _harmony = new Harmony("com.zach.BetterControls"); _harmony.PatchAll(typeof(BetterControls)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"BetterControls reflection fix loaded."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)"BetterControls failed to patch. DSP may have changed too much."); ((BaseUnityPlugin)this).Logger.LogError((object)ex); } } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } Log = null; } } public static class KeyIds { public const int Jump = 8; public const int Takeoff = 9; public const int ClosePanel0 = 32; public const int Inventory = 34; public const int ClosePanel1 = 33; public const int GameMenu = 47; } internal static class BetterControls { private static bool[] conflicts; private static readonly Dictionary indexes = new Dictionary(); private static readonly Dictionary groups = new Dictionary(); private static readonly Dictionary linked = new Dictionary(); private static FieldInfo Field(Type type, string name) { return AccessTools.Field(type, name); } private static T GetField(object obj, string name) { if (obj == null) { return default(T); } FieldInfo fieldInfo = Field(obj.GetType(), name); if (fieldInfo == null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("Missing field " + obj.GetType().Name + "." + name)); } return default(T); } return (T)fieldInfo.GetValue(obj); } private static bool SetField(object obj, string name, object value) { if (obj == null) { return false; } FieldInfo fieldInfo = Field(obj.GetType(), name); if (fieldInfo == null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("Missing field " + obj.GetType().Name + "." + name)); } return false; } fieldInfo.SetValue(obj, value); return true; } private static object Call(object obj, string methodName, params object[] args) { if (obj == null) { return null; } MethodInfo methodInfo = AccessTools.Method(obj.GetType(), methodName, (Type[])null, (Type[])null); if (methodInfo == null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("Missing method " + obj.GetType().Name + "." + methodName)); } return null; } return methodInfo.Invoke(obj, args); } private static CombineKey GetKey(CombineKey builtin, CombineKey overrider) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (!((CombineKey)(ref overrider)).IsNull()) { return overrider; } return builtin; } public static bool InventoryKeyDown() { try { if (VFInput.override_keys != null && VFInput.override_keys.Length > 34 && !((CombineKey)(ref VFInput.override_keys[34])).IsNull()) { return ((CombineKey)(ref VFInput.override_keys[34])).GetKeyDown(); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("Inventory override check failed; falling back to E. " + ex.Message)); } } if (VFInput.noModifier) { return Input.GetKeyDown((KeyCode)101); } return false; } public static bool MenuKeyDown() { try { if (VFInput.override_keys != null && VFInput.override_keys.Length > 47 && !((CombineKey)(ref VFInput.override_keys[47])).IsNull()) { return ((CombineKey)(ref VFInput.override_keys[47])).GetKeyDown(); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("Menu override check failed; falling back to Escape. " + ex.Message)); } } if (VFInput.noModifier) { return Input.GetKeyDown((KeyCode)27); } return false; } [HarmonyTranspiler] [HarmonyPatch(typeof(UIGame), "_OnUpdate")] private static IEnumerable PatchInventoryKey(IEnumerable instructions, ILGenerator generator) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(Input), "GetKeyDown", new Type[1] { typeof(KeyCode) }, (Type[])null); MethodInfo operandAndAdvance = AccessTools.Method(typeof(BetterControls), "InventoryKeyDown", (Type[])null, (Type[])null); CodeMatcher val = new CodeMatcher(instructions, generator).MatchForward(false, (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((Func)((CodeInstruction ci) => CodeInstructionExtensions.LoadsConstant(ci, (Enum)(object)(KeyCode)101)), (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)methodInfo, (string)null) }); if (!val.IsValid) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"Could not find the hardcoded E inventory check in UIGame._OnUpdate. Skipping inventory patch."); } return instructions; } ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)"Patched UIGame._OnUpdate inventory key check."); } return val.RemoveInstruction().SetOperandAndAdvance((object)operandAndAdvance).InstructionEnumeration(); } [HarmonyPostfix] [HarmonyPatch(typeof(VFInput), "OnUpdate")] private static void OnVFInputUpdate() { try { VFInput.escape = MenuKeyDown() && !VFInput.inputing; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("Menu key patch failed this frame. " + ex.Message)); } } } [HarmonyPostfix] [HarmonyPatch(typeof(UIOptionWindow), "_OnOpen")] private static void OptionWindowOnOpen(UIOptionWindow __instance) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_008b: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Unknown result type (might be due to invalid IL or missing references) try { BuiltinKey[] builtinKeys = DSPGame.key.builtinKeys; GameOption field = GetField(__instance, "tempOption"); UIKeyEntry[] field2 = GetField(__instance, "keyEntries"); if (builtinKeys == null || field2 == null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"BetterControls could not access option window key data. UI features skipped."); } return; } CombineKey[] overrideKeys = field.overrideKeys; int num = builtinKeys.Length; CombineKey[] array = (CombineKey[])(object)new CombineKey[num]; indexes.Clear(); groups.Clear(); linked.Clear(); for (int i = 0; i < num; i++) { BuiltinKey val = builtinKeys[i]; array[i] = GetKey(val.key, overrideKeys[val.id]); indexes[val.id] = i; } for (int j = 0; j < num - 1; j++) { CombineKey key = builtinKeys[j].key; if (groups.ContainsKey(j)) { continue; } groups[j] = -1; for (int k = j + 1; k < num; k++) { CombineKey key2 = builtinKeys[k].key; if (((CombineKey)(ref key)).IsEquals(key2.keyCode, key2.modifier, key2.noneKey)) { groups[j] = j; groups[k] = j; } } } if (!groups.ContainsKey(num - 1)) { groups[num - 1] = -1; } conflicts = new bool[num]; for (int l = 0; l < num - 1; l++) { CombineKey val2 = array[l]; if (conflicts[l]) { continue; } for (int m = l + 1; m < num; m++) { CombineKey val3 = array[m]; if ((((BuiltinKey)(ref builtinKeys[l])).conflictKeyGroup & ((BuiltinKey)(ref builtinKeys[m])).conflictKeyGroup) > 0 && (groups[l] != groups[m] || groups[l] < 0) && ((CombineKey)(ref val2)).IsEquals(val3.keyCode, val3.modifier, val3.noneKey)) { conflicts[l] = true; conflicts[m] = true; } } } int[] array2 = new int[6] { 9, 8, 32, 34, 33, 47 }; for (int n = 0; n < array2.Length; n += 2) { if (!indexes.ContainsKey(array2[n]) || !indexes.ContainsKey(array2[n + 1])) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("BetterControls could not find linked key ids " + array2[n] + " and " + array2[n + 1])); } continue; } int num2 = indexes[array2[n]]; int num3 = indexes[array2[n + 1]]; linked[num2] = num3; linked[num3] = num2; CombineKey val4 = array[num3]; if (!((CombineKey)(ref array[num2])).IsEquals(val4.keyCode, val4.modifier, val4.noneKey) && num2 >= 0 && num2 < field2.Length && (Object)(object)field2[num2] != (Object)null) { Call(field2[num2], "OverrideKey", field, val4.keyCode, val4.modifier, val4.noneKey); } } ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogInfo((object)"BetterControls option-window reflection patch ran."); } } catch (Exception ex) { ManualLogSource log4 = Plugin.Log; if (log4 != null) { log4.LogWarning((object)("BetterControls option-window patch failed: " + ex)); } } } [HarmonyPrefix] [HarmonyPatch(typeof(BuiltinKey), "IsKeyVaild")] private static bool IsKeyValid(ref bool __result) { __result = true; return false; } [HarmonyPostfix] [HarmonyPatch(typeof(UIKeyEntry), "SetEntry")] private static void SetEntry(UIKeyEntry __instance, int _index, BuiltinKey _builtinKey, UIOptionWindow _optionWin) { //IL_0000: 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) try { if (_builtinKey.id < 71 || 78 < _builtinKey.id) { ((Component)__instance.setTheKeyInput).gameObject.SetActive(true); ((Component)__instance.setTheKeyToggle).gameObject.SetActive(true); ((Component)__instance.setDefaultUIButton).gameObject.SetActive(true); ((Component)__instance.setNoneKeyUIButton).gameObject.SetActive(true); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("SetEntry patch failed: " + ex.Message)); } } } [HarmonyPostfix] [HarmonyPatch(typeof(UIKeyEntry), "Update")] private static void Update(UIKeyEntry __instance) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_0053: Unknown result type (might be due to invalid IL or missing references) try { if (conflicts != null && !((Object)(object)__instance == (Object)null)) { BuiltinKey field = GetField(__instance, "builtinKey"); if (indexes.TryGetValue(field.id, out var value) && value >= 0 && value < conflicts.Length && conflicts[value]) { ((Graphic)__instance.keyText).color = Color.red; } } } catch { } } [HarmonyPrefix] [HarmonyPatch(typeof(UIKeyEntry), "OnSetNoneKeyClick")] private static bool OnSetNoneKeyClick(UIKeyEntry __instance) { //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_003d: Unknown result type (might be due to invalid IL or missing references) try { UIOptionWindow field = GetField(__instance, "optionWin"); if ((Object)(object)field == (Object)null) { return true; } GameOption val = (GameOption)Call(field, "GetTempOption"); Call(__instance, "OverrideKey", val, 0, (byte)0, true); return false; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("OnSetNoneKeyClick patch failed: " + ex.Message)); } return true; } } [HarmonyPrefix] [HarmonyPatch(typeof(UIKeyEntry), "OverrideKey")] private static bool OverrideKey(UIKeyEntry __instance, GameOption tempOption, int keyCode, byte modifier, bool noneKey) { //IL_0012: 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_0054: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_040e: Unknown result type (might be due to invalid IL or missing references) //IL_042d: Unknown result type (might be due to invalid IL or missing references) try { UIOptionWindow field = GetField(__instance, "optionWin"); BuiltinKey field2 = GetField(__instance, "builtinKey"); if ((Object)(object)field == (Object)null) { return true; } if (__instance.inputUIButton._isPointerEnter && Input.GetKeyDown((KeyCode)323)) { SetField(__instance, "nextNotOn", true); } int id = field2.id; if (!indexes.TryGetValue(id, out var value)) { return true; } CombineKey key = field2.key; BuiltinKey[] builtinKeys = DSPGame.key.builtinKeys; CombineKey[] overrideKeys = tempOption.overrideKeys; int num = builtinKeys.Length; CombineKey[] array = (CombineKey[])(object)new CombineKey[num]; for (int i = 0; i < num; i++) { array[i] = GetKey(builtinKeys[i].key, overrideKeys[builtinKeys[i].id]); } int keyCode2 = array[value].keyCode; byte modifier2 = array[value].modifier; bool noneKey2 = array[value].noneKey; int num2 = keyCode; byte b = modifier; bool flag = noneKey; if (keyCode == 0 && modifier == 0 && !noneKey) { num2 = key.keyCode; b = key.modifier; flag = key.noneKey; } if (keyCode2 == num2 && modifier2 == b && noneKey2 == flag) { __instance.inputUIButton.highlighted = false; return false; } if (((CombineKey)(ref key)).IsEquals(num2, b, flag)) { ((CombineKey)(ref overrideKeys[id])).Reset(); } else { overrideKeys[id].keyCode = num2; overrideKeys[id].modifier = b; overrideKeys[id].noneKey = flag; } field.SetTempOption(tempOption); __instance.inputUIButton.highlighted = false; int num3 = -1; for (int j = 0; j < num; j++) { if (j != value && conflicts != null && conflicts[j] && (((BuiltinKey)(ref builtinKeys[j])).conflictKeyGroup & ((BuiltinKey)(ref builtinKeys[value])).conflictKeyGroup) > 0 && (groups[j] != groups[value] || groups[j] < 0) && ((CombineKey)(ref array[j])).IsEquals(keyCode2, modifier2, noneKey2)) { if (num3 > -1 && (!linked.ContainsKey(num3) || linked[num3] != j)) { num3 = -1; break; } num3 = j; } } if (num3 > -1 && conflicts != null) { conflicts[num3] = false; if (linked.ContainsKey(num3)) { conflicts[linked[num3]] = false; } } if (conflicts != null) { conflicts[value] = false; } for (int k = 0; k < num; k++) { if (k == value || (((BuiltinKey)(ref builtinKeys[k])).conflictKeyGroup & ((BuiltinKey)(ref builtinKeys[value])).conflictKeyGroup) <= 0 || (groups[k] == groups[value] && groups[k] >= 0) || !((CombineKey)(ref array[k])).IsEquals(num2, b, flag)) { continue; } if (conflicts != null) { conflicts[k] = true; conflicts[value] = true; if (linked.ContainsKey(k)) { conflicts[linked[k]] = true; } } Call(__instance, "StartConflictText", k); __instance.setTheKeyToggle.isOn = false; ((Component)__instance.waitingText).gameObject.SetActive(false); break; } if (linked.ContainsKey(value)) { UIKeyEntry[] field3 = GetField(field, "keyEntries"); int num4 = linked[value]; if (field3 != null && num4 >= 0 && num4 < field3.Length && (Object)(object)field3[num4] != (Object)null && GetField(field3[num4], "builtinKey").id != id) { Call(field3[num4], "OverrideKey", tempOption, num2, b, flag); } } return false; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("OverrideKey reflection patch failed; letting original run. " + ex.Message)); } return true; } } } }