This is my first time using Harmony and IL and I am trying to do what I mention in the title. I want to skip the instruction because it calls a method that I do not want to be called. Here is what I have so far in my patch class:
// Logs to show when the instruction is called
static void TestMethod() {
Plugin.pluginLog.LogWarning("TestMethod has been called!");
}
private static MethodInfo methodToSkip = AccessTools.Method(typeof(GameClass), "MethodToSkip");
static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) {
int found = 0;
foreach (CodeInstruction instr in instructions) {
if (instr.opcode == OpCodes.Callvirt && instr.Calls(methodToSkip)) {
found++;
yield return new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(TestPatch), nameof(TestMethod)));
}
yield return instr;
}
if (found == 0) {
Plugin.pluginLog.LogError($"Cannot find symbol {methodToSkip}");
} else {
Plugin.pluginLog.LogWarning($"Found {found} occurrences of {methodToSkip}");
}
}
I am able to trigger the log when the instruction is called, but the method I am trying to skip is still called - probably because of the yield return instr
line? The issue is if I put that line in an else block following the if statement I get the error "InvalidProgramException: Invalid IL code...". I'm not sure why skipping an instruction would make it invalid, unstable sure but why does Harmony fail to run it.
Try setting a local variable and always returning it. This allows you to have a single
yield return
in the function.