-
Notifications
You must be signed in to change notification settings - Fork 44
Home
NOTE: This documentation refers to HarmonyX 2.1 and newer.
You can still use the information for Harmony 2 as core API is the same, but note that some of API might be missing.
A library for patching, replacing and decorating .NET methods during runtime powered by MonoMod.
This wiki contains information related to HarmonyX -- that is, the extensions we added to Harmony 2. When it comes to base Harmony features, we attempt to keep our API consistent with latest Harmony code. Because of that, you can use official Harmony docs.
As such:
- If you're looking for base Harmony guide, use official Harmony 2 documentation
- Use this wiki to check the additions and extensions introduced by HarmonyX. Check the links in the sidebar for all topics.
If you develop in C# and your code is loaded as a module/plugin into a host application, you can use HarmonyX (later referred to as Harmony) to alter the functionality of all the available assemblies of that application. Where other patch libraries simply allow you to replace the original method, Harmony goes one step further and gives you:
- A way to keep the original method intact
- Execute your code before and/or after the original method
- Modify the original with IL code processors
- Multiple Harmony patches co-exist and don't conflict with each other
HarmonyX builds on top the original Harmony library, extending and streamlining its features. Most importantly, you get
- Better logging via streamlined API
- Helper methods to make
- Easy extendibility to support patching special methods (like IL2CPP methods)
- Reduce overall complexity and code duplication by using helpers from MonoMod instead of reimplementing them
At the same time, HarmonyX is based on MonoMod, a robust tool for patching .NET assemblies. With it, you get additional features such as
- Ability to target methods marked with
extern
- Ability to use HarmonyX in environments where dynamic code generation is not supported (e.g. Unity's .NET Standard 2.0 API)
- Interop with MonoMod patches
HarmonyX works on any games that support running code in .NET. Currently HarmonyX is built against the following targets:
- .NET Framework 3.5
- .NET Framework 4.0
- .NET Standard 2.0
HarmonyX has been tested mainly on Unity games and has been confirmed to work on all Unity versions (even ones with dynamic code generation disabled).
HarmonyX supports patching on all architectures that MonoMod supports. At the time of the writing, that is x86, x64, ARM, ARM64.
NOTE: HarmonyX design is strongly motivated by our needs in BepInEx that arised over time. While Harmony aims at general runtime patching, our target is to make Harmony "modding-framework-friendly". You might not agree with all our changes, but they proved to be useful enough to warrant a custom fork.
Without a long essay on the history of BepInEx Harmony forks and our needs to integrate it with MonoMod, here are some points:
- Logging: current Harmony 2 logging system is primitive and not enough for modding frameworks. We added a custom extendable logging system to facilitate custom log levels, lazy logging and multiple log targets.
- Remove "global patch state": in modding frameworks there is only one source of Harmony. Instead of slowdown of serializing patch state and handle version incompatibilities we prefer assembly shimming.
- Interop with MonoMod.RuntimeDetours to support modding communities that use it primarily.
- Remove duplicated code between MonoMod and Harmony where possible: IL parsing, delegate generation should be done by only one library. We use MonoMod.Common to its full capabilities to remove duplicated code from Harmony.
- Don't hide useful code, allow extendability: most of internal patching code is made public as helpers. Custom patching backends can be implemented to support patching new methods (e.g. native methods and il2cpp methods)
- Helper methods to make life easier: unpatch current instance, patch specified type, emit call to a delegate, code matching. We've seen too many plugin makers call
instance.UnpatchAll
thinking it will unpatch just the current instance.
For a more specific explanation of more technical changes, refer to implementation difference outline.
- 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