- C# 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| Consensus | ||
| ConsensusTest | ||
| lib | ||
| .gitattributes | ||
| .gitignore | ||
| Consensus.sln | ||
| LICENSE | ||
| README.md | ||
Consensus [obsolete]
An add-on library for Harmony, that allows patching of enumerator methods.
This library is obsolete
Since Harmony v2.2.1.0, this library is no longer needed for patching Enumerators.
You can now specify a new MethodType in the HarmonyPatch-Attribute constructor to patch Enumerators
Example:
[HarmonyPatch(typeof(ClassWithEnumeratorMethod), nameof(SomeEnumeratorMethod), MethodType.Enumerator)]
The problem
One annoying limitation of Harmony, is that it currently does not support patching Enumerator methods properly.
Enumerator methods are more complicated beneath the surface than they appear, as they just return an object of a hidden class which does all the work.
The solution
Consensus redirects a Harmony patch from the normal enumerator method to its internal Current property or MoveNext method instead.
Known limitations
- The
__instancevariable ofPrefixandPostfixmethods receives the underlying Enumerator object instead of the object where the Enumerator was defined.
Build requirements
Add 0Harmony.dll from Harmony or HarmonyX to the lib directory to build it.
Usage
Using the attribute method
After you have created your Harmony instance, you need to pass it to ConsensusPatcher.Patch before patching anything.
Harmony harmonyInstance = new Harmony("your.harmony.id");
ConsensusPatcher.Patch(harmonyInstance);
harmonyInstance.PatchAll();
You can add the [Consensus] attribute to an existing harmony patch attribute.
The attribute takes an optional parameter, which chooses whether the patch should be redirected to the Current property or the MoveNext method.
The attribute without parameters will always redirect to the MoveNext method.
[Consensus(PatchEnumerator.MoveNext)]
[HarmonyPatch(typeof(ClassWithEnumeratorMethod), nameof(SomeEnumeratorMethod))]
internal class SomeEnumeratorMethodPatch
{
...
}
Check the ConsensusTest project for a real example.
Manually patching an enumerator
If you want to patch a enumerator method manually, then you can use the GetCurrent and GetMoveNext helper methods of the ConsensusPatcher class.
Harmony harmonyInstance = new Harmony("your.harmony.id");
MethodInfo original = AccessTools.Method(typeof(ClassWithEnumeratorMethod), nameof(SomeEnumeratorMethod));
MethodInfo prefix = AccessTools.Method(typeof(SomeEnumeratorMethodPatch), nameof(SomeEnumeratorMethodPrefix));
MethodInfo postfix = AccessTools.Method(typeof(SomeEnumeratorMethodPatch), nameof(SomeEnumeratorMethodPostfix));
MethodInfo transpiler = AccessTools.Method(typeof(SomeEnumeratorMethodPatch), nameof(SomeEnumeratorMethodTranspiler));
harmonyInstance.Patch(ConsensusPatcher.GetMoveNext(original), new HarmonyMethod(prefix), new HarmonyMethod(postfix), new HarmonyMethod(transpiler));
Check the ConsensusTest project for a real example.
Additional Info
- .NET Standard 2.0
- Visual Studio 2019
- C# 9