How the template initialises Harmony
The template’sInit method creates a Harmony instance keyed to your plugin’s unique ID and then calls PatchAll, which scans every type in your assembly for [HarmonyPatch] classes:
Assembly.GetExecutingAssembly() returns your plugin’s DLL. PatchAll walks every class in it and automatically applies any it finds decorated with [HarmonyPatch]. You do not need to register patches individually.
Writing a prefix patch
A prefix runs before the original method. Returningfalse from a bool-returning prefix skips the original entirely; returning true (or using void) lets it proceed.
The example below intercepts BeatmapObjectContainerCollection.AddObject to log every time an object is added to the map:
- Logging or telemetry before an action
- Validating or modifying arguments before they reach the original method
- Blocking the original method entirely under certain conditions
Writing a postfix patch
A postfix runs after the original method. Use the special__result parameter (prefixed with two underscores) to read or replace the return value.
- Reading the return value of a method
- Performing clean-up or notifications after an operation completes
- Chaining additional behaviour onto an existing method
How PatchAll discovers your patches
When you call PatchAll(Assembly.GetExecutingAssembly()), Harmony looks for every class in your assembly that has at least one [HarmonyPatch] attribute and applies all prefix, postfix, and transpiler methods it finds inside them. You can have as many patch classes as you need — just add [HarmonyPatch] and they are picked up automatically on next plugin load.
Targeting a specific method overload
Targeting a specific method overload
When a method is overloaded, supply the parameter types to
[HarmonyPatch] to select the right one:Using __instance to access the patched object
Using __instance to access the patched object
Declare a parameter named
__instance with the patched type to get a reference to the object the method was called on:Krafs.Publicizer: accessing private and internal members
ChroMapper’s assemblies contain manyinternal and private types and members that you need to interact with. Normally, C# prevents you from referencing them at compile time.
Krafs.Publicizer (version 2.3.0, declared in packages.config) is a Roslyn source generator that runs at build time. It produces a thin public API surface over ChroMapper’s assemblies so you can reference internal fields, methods, and types directly in your code — without reflection, without AccessTools, and with full IntelliSense support.
developmentDependency, Krafs.Publicizer is consumed only at build time and produces no runtime dependency. Your output DLL does not include it, and ChroMapper does not need to have it installed.
You must restore NuGet packages before the first build. Run
nuget restore in the solution directory, or let Visual Studio restore packages automatically when you open the project. See Build and deploy for details.