-
Notifications
You must be signed in to change notification settings - Fork 44
ILManipulators
In addition to the normal Harmony transpiler, HarmonyX provides the additional ILManipulator
patch type, which enables the use of common MonoMod helpers such as ILCursor
. There are several optional parameters you can use in these patches:
-
ILContext
- An ILContext for the method you're manipulating. Use this to interact with the rest of the MonoMod library. -
MethodBase
- The MethodBase of the original method you're manipulating. -
ILLabel
- A label to the end of the original. How this label is intended to be used will be discussed in a later section. Not much use in Reverse Patches.
ILManipulators are meant as an alternative to Transpilers, and are fully integrated and compatible with everything else that Harmony provides.
ILManipulators run after all other patch types have been applied (this is due to a technical limitation and making sure existing patches work as expected). This can lead to some easy errors when you start with ILManipualtors, and you should keep in mind these conditions when designing your patches.
Because of how prefixes, postfixes, and finalizers are applied to methods, they will be inside the method body by the time your patch runs. This has several repercussions when it comes to what you write:
- All
ret
opcodes in the method will have becomebr
opcodes that branch to the beginning of where the postfixes and finalizers run.- This means that you should be careful about adding
ret
opcodes yourself, as that will skip all postfixes and finalizers applied to the method. - You in order to avoid emitting
ret
opcodes yourself, you can use the optionalILLabel
parameter to unconditionally branch to where postfixes and finalizers begin.
- This means that you should be careful about adding
- Since Harmony may have changed the method before your patch recieves it, the IL may not be exactly the same as what ILSpy/dnSpy/dotPeek tell you.
- If you need to see the exact IL Harmony generates, enable the
IL
log channel in your configs.
- If you need to see the exact IL Harmony generates, enable the
ILManipulators can be used in all of the same contexts as Transpilers, with an attribute, with the correct name, or as part of a Reverse Patch.
ILManipulators should always return void
.
Examples for each usage:
public class ExampleClassToBePatched
{
public string ExampleMethod()
{
return "example string";
}
}
[HarmonyPatch(typeof(ExampleClassToBePatched), "ExampleMethod")]
public class PatchClass
{
// With the correct naming scheme
public static void ILManipulator(ILContext il, MethodBase original, ILLabel retLabel) { }
// With the correct attribute applied to the method
[HarmonyILManipulator]
public static void SomeOtherILManipulator(ILContext ctx, MethodBase orig) { } // parameter names can be anything, all parameters are optional
// As part of a reverse patch
[HarmonyReversePatch]
[MethodImpl(MethodImplOptions.NoInlining)] // make sure the method is never inlined so the patch as actually called in our code
public static string ExampleMethodReverse()
{
void Manipulator(ILContext il) { } // manipulator method can be named anything, and all parameters are optional
Manipulator(null); // get rid of compiler warning about unused method
return default(string); // get rid of compiler error about no value being returned
}
}
TODO: Write comprehensive examples unique to HarmonyX
To see more details about implementation of MonoMod's ILContext and its helpers to manipulate it, please reference:
TODO: Find more resources for MonoMod's helpers
- Basic usage
-
HarmonyX extensions
1.1. Patching and unpatching
1.2. Prefixes are flowthrough
1.3. Targeting multiple methods with one patch
1.4. Patching enumerators
1.5. Transpiler helpers
1.6. ILManipulators
1.7. Extended patch targets
1.8. New patch attributes -
Extending HarmonyX
2.1. Custom patcher backends -
Misc
4.1. Patch parameters - Implementation differences from Harmony