Skip to content

Patch parameters

Geoffrey Horsington edited this page Jan 10, 2022 · 9 revisions

Prefix, postfix and finalizers allow you to access various special parameters to modify the behaviour of the patch.

This table contains description of all parameters that are allowed in prefixes, postfixes and finalizers. Note that

  • You can mark all parameters as either normally or by reference (by using ref)
    • Passing parameter by reference allows you to edit it
  • You don't have to pass all parameters
  • The order of parameters does not matter, but their name does
Parameter name Type Description
__state Any, defined by the patcher A local state that is defined by. Use this to share data between different patch types. Remember to pass it by reference to be able to edit it.
__instance Type that declares the target method or object. If the method being patched is an instance method (i.e. not static), the parameter will have the instance of the class on which the original method is declared. If the method is static, will always be null.
__result Return type of the original method If method returns a value, this will contain the return value of the method. Changing it will change the return value of the method.
__originalMethod MethodBase The MethodBase of the original method that was patched. Note that invoking it will invoke the Harmony patch too. Cannot be passed by reference.
__runOriginal bool Behaves the same as return value of the prefix. If set to false, original method code is not run. Use this in prefix to determine if a patch before yours wishes to skip running the original method.
__exception Exception or its subtype. In finalizers, this parameter will have an exception that is caught. If set to null, the exception will be supressed. If set to a value, an exception will the thrown.
__<idx> where <idx> is an integer. Same type as original method's argument at index <idx>. Original method's argument located at index <idx>. The index is zero-based, where method's first argument is at index 0.
<name> where it is a valid argument name Same type type as original method's argument with name <name>. Original method's argument with the name <name>.
___<name> where <name> is the name of a field inside the declaring class. Same type as the field <name> in declaring class of the original method. This will contain a value of any field with name <name> that is declared in the type where the original method resides. You can access and modify field values this way.
__args object[] All arguments of the original methods as an object[] array. Allows handling changing parameters or patching methods with different parameters.

Transpiler parameters

Transpilers have a different set of parameters available for use.
Note that in transpilers the name does not matter, only types.

Parameter type Description
IEnumerable<CodeInstruction> Required. The list of IL instructions of the original method.
ILGenerator The IL generator that is used to generate the Harmony patch. Use this to define labels.
MethodInfo The info pointing to the original method.

ILManipulator parameters

ILManipulators also have a unique set of parameters to other patch types. Same as transpilers, parameter names do not matter, only types.

Parameter type Description
ILContext ILContext of the method you're manipulating, base to interact with the rest of MonoMod.
MethodBase MethodBase for the method you're manipulating.
ILLabel ILLabel to the end of the original method that you can emit a br to. For implementation details, see the ILManipulators page.

Some examples

// An example of the original target method
class Customer
{
    private int myField;

    // original method in class Customer
    private List<string> getNames(int count, out Error error);
}

// prefix
// - wants instance, result and count
// - wants to change method argument `count`
// - sets a state that can be accessed by the Postfix
// - returns a boolean that controls if original is executed (true) or not (false)
static bool Prefix(Customer __instance, List<string> __result, ref int count, out int __state);

// postfix
// - wants result and method argument `error`
// - does not change any of those
// - receives the state value that was set in the Prefix
static void Postfix(List<string> __result, Error error, int __state);

// transpiler
// - wants to use original method
static IEnumerable<CodeInstruction> Transpiler(MethodBase original, IEnumerable<CodeInstruction> instructions);

// ilmanipulator
// - wants the ILContext of the method to manipulate it
// - wants a label to the end of the original method to jump to
static void ILManipulator(ILContext il, ILLabel retLabel);

// finalizer
// - wants the caught exception
// - wants the 0th method argument (count)
// - wants the myField
static void Finalizer(ref Exception __exception, int __0, int ___myField);