using System.Collections.Generic; using System.Reflection.Emit; using BepInEx.Configuration; using HarmonyLib; namespace CheatEnabler; public static class DevShortcuts { public static ConfigEntry Enabled; private static Harmony _patch; private static PlayerAction_Test _test; public static void Init() { _patch = Harmony.CreateAndPatchAll(typeof(DevShortcuts)); Enabled.SettingChanged += (_, _) => { if (_test != null) _test.active = Enabled.Value; }; } public static void Uninit() { if (_patch == null) return; _patch.UnpatchSelf(); _patch = null; } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerController), "Init")] private static void PlayerController_Init_Postfix(PlayerController __instance) { var cnt = __instance.actions.Length; var newActions = new PlayerAction[cnt + 1]; for (var i = 0; i < cnt; i++) { newActions[i] = __instance.actions[i]; } _test = new PlayerAction_Test(); _test.Init(__instance.player); _test.active = Enabled.Value; newActions[cnt] = _test; __instance.actions = newActions; } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerAction_Test), "GameTick")] private static void PlayerAction_Test_GameTick_Postfix(PlayerAction_Test __instance) { __instance.Update(); } [HarmonyTranspiler] [HarmonyPatch(typeof(PlayerAction_Test), nameof(PlayerAction_Test.Update))] private static IEnumerable PlayerAction_Test_Update_Transpiler(IEnumerable instructions, ILGenerator generator) { var matcher = new CodeMatcher(instructions, generator); matcher.End().MatchBack(false, new CodeMatch(OpCodes.Ldarg_0), new CodeMatch(OpCodes.Ldfld, AccessTools.Field(typeof(PlayerAction_Test), nameof(PlayerAction_Test.active))) ); var pos = matcher.Pos; /* Remove Shift+F4 part of the method */ matcher.Start().RemoveInstructions(pos); matcher.Start().MatchForward(false, new CodeMatch(OpCodes.Call, AccessTools.Method(typeof(GameMain), "get_sandboxToolsEnabled")), new CodeMatch(OpCodes.Ldc_I4_0), new CodeMatch(OpCodes.Ceq) ); var labels = matcher.Labels; matcher.SetInstructionAndAdvance( new CodeInstruction(OpCodes.Ldc_I4_1).WithLabels(labels) ).RemoveInstructions(2); return matcher.InstructionEnumeration(); } }