I need to replace a method with a call to a method with the same signature so that I can essentially replace the original method with a new method. Currently, I have the code below, which works, but when I try to patch the method again, it simply does nothing. I'm not sure if that's because Harmony doesn't like when I try to transpile it twice, or something else, either way it prevents me from repeatedly redirecting the original method.
// this is factored out of Transpiler() because yield return reasons
private static IEnumerable<CodeInstruction> TranspilerIterator(IEnumerable<CodeInstruction> instructions,
MethodBase original) {
var name = original.Name;
var par = original.GetParameters();
var method = newGuiType.GetMethod(name, (BindingFlags) FLAGS);
Console.WriteLine($"{name} == null == {method == null}");
if ((method.CallingConvention & CallingConventions.HasThis) != 0)
yield return new CodeInstruction(OpCodes.Ldarg_0);
for (var i = 0; i < par.Length; i++)
yield return new CodeInstruction(OpCodes.Ldarg_S, par[i].Position + 1);
yield return new CodeInstruction(OpCodes.Call, method);
yield return new CodeInstruction(OpCodes.Ret);
}
which is called by this:
private void DoPatches() {
Logger.Debug("Performing patches.");
var methods = oldGuiType.GetMethods((BindingFlags) FLAGS);
var t = this.GetType().GetMethod("Transpiler", BindingFlags.NonPublic | BindingFlags.Static);
for (var i = 0; i < methods.Length; i++) {
var name = methods[i].Name;
Logger.Debug($"Transpiling {name}");
harmony.Patch(methods[i], transpiler: new HarmonyMethod(t));
}
}
I can't use a prefix because I need to know the signature to get the args in a prefix, and I don't know the signature.
I know there are other libraries to make essentially this, but the game I'm modding ships with Harmony so I don't have to ship a whole lib with my very small mod.