-
Notifications
You must be signed in to change notification settings - Fork 7
Free patching
Free patching will likely get removed in the future in favor of more structured options.
Prepatcher calls all static methods annotated [FreePatch]
having a single Mono.Cecil.ModuleDefinition
parameter after it finishes applying its normal patches.
The method has to be in a static class.
An example of a free patch from Prepatcher's test suite:
public static class FreePatching
{
[FreePatch]
static void RewriteAssembly(ModuleDefinition module)
{
var type = module.GetType($"{nameof(TestAssemblyTarget)}.{nameof(RewriteTarget)}");
var method = type.FindMethod(nameof(RewriteTarget.Method));
foreach (var inst in method.Body.Instructions)
if (inst.OpCode == OpCodes.Ldc_I4_0)
inst.OpCode = OpCodes.Ldc_I4_1;
}
}
Note that the Mono.Cecil.ModuleDefinition
used here is currently the one bundled internally inside 0Harmony
(you might have to publicize it).
Each method is called once and the parameter is supplied with RimWorld's AssemblyCSharp.dll
about to be reloaded. This allows mods to mutate the game's assembly freely applying any patches.
The methods are called in the order of the mod list.
This is an advanced feature, you are on your own and no support is provided. Creating incompatibilities with other mods and breaking the game is very easy to achieve using this tool but at the same time it is very powerful.
It exists because Prepatcher's current API is fairly minimal. It is meant to be used mostly for experimentation.
In addition to the FreePatch
attribute, a FreePatchAll
attribute is available which works the same way but gets called with every patchable assembly that Prepatcher processes.
The patchable assemblies are: all mod assemblies and RimWorld's Assembly-CSharp.dll.
System assemblies (Unity and .NET assemblies from RimWorldWin64_Data/Managed
) are not patchable.
An example:
[FreePatchAll]
static bool RewriteAssembly(ModuleDefinition module)
{
if (module.Name != "Assembly-CSharp.dll")
return false;
// Do patches on Assembly-CSharp.dll...
return true;
}
All free patches can optionally return a bool
signifying whether the free patch modified the given assembly. A void
return type is treated like returning true
.
This is a performance hint: if an assembly is not modified Prepatcher doesn't have to serialize it which speeds up loading.