Skip to content

Instantly share code, notes, and snippets.

@pardeike
Created April 7, 2024 22:29
Show Gist options
  • Save pardeike/f3f509cae604fafb61e50af2366fa4b1 to your computer and use it in GitHub Desktop.
Save pardeike/f3f509cae604fafb61e50af2366fa4b1 to your computer and use it in GitHub Desktop.
How infixes will be better than transpilers
public static readonly StringBuilder buffer = new StringBuilder();
void Main()
{
// first mod adds transpiler
Console.WriteLine("// APPLYING PATCH 1");
var h1 = new Harmony("test1");
h1.CreateClassProcessor(typeof(Patch1)).Patch();
// second mod adds transpiler
Console.WriteLine("\n// APPLYING PATCH 2");
var h2 = new Harmony("test2");
h2.CreateClassProcessor(typeof(Patch2)).Patch();
// method runs
Console.WriteLine("\n// TESTING");
var test = new Test();
test.Method();
test.Method();
// result
Console.WriteLine("\n// LOG RESULTS");
Console.WriteLine(buffer.ToString());
}
[HarmonyPatch(typeof(Test), nameof(Test.Method))]
static class Patch1
{
static void LogItInstead1(string str)
{
buffer.Append($"log1:{str}\n");
Console.WriteLine(str);
}
static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
var from = AccessTools.Method(typeof(Console), nameof(Console.WriteLine), new Type[] { typeof(string) });
var to = SymbolExtensions.GetMethodInfo(() => LogItInstead1(default));
var found = false;
foreach(var instruction in instructions)
{
if (instruction.operand is MethodInfo m && m == from)
{
instruction.opcode = OpCodes.Call;
instruction.operand = to;
found = true;
}
yield return instruction;
}
if (found)
Console.WriteLine($"Transpiler 1 - Ok");
else
Console.WriteLine($"Transpiler 1, error: cannot find {from.FullDescription()}");
}
}
[HarmonyPatch(typeof(Test), nameof(Test.Method))]
[HarmonyPriority(Priority.High)]
static class Patch2
{
static void LogItInstead2(string str)
{
buffer.Append($"log2:{str}\n");
Console.WriteLine(str);
}
static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
var from = AccessTools.Method(typeof(Console), nameof(Console.WriteLine), new Type[] { typeof(string) });
var to = SymbolExtensions.GetMethodInfo(() => LogItInstead2(default));
var found = false;
foreach(var instruction in instructions)
{
if (instruction.operand is MethodInfo m && m == from)
{
instruction.opcode = OpCodes.Call;
instruction.operand = to;
found = true;
}
yield return instruction;
}
if (found)
Console.WriteLine($"Transpiler 2 - Ok");
else
Console.WriteLine($"Transpiler 2, error: cannot find {from.FullDescription()}");
}
}
public class Test
{
public void Method()
{
Console.WriteLine("Test");
}
}
@pardeike
Copy link
Author

pardeike commented Apr 7, 2024

Output:

// APPLYING PATCH 1
Transpiler 1 - Ok

// APPLYING PATCH 2
Transpiler 2 - Ok
Transpiler 1, error: cannot find static System.Void System.Console::WriteLine(System.String value)

// TESTING
Test
Test

// LOG RESULTS
log2:Test
log2:Test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment