Skip to content

Instantly share code, notes, and snippets.

@zzzz465
Last active January 30, 2020 14:48
Show Gist options
  • Save zzzz465/36189fd288c66d90d70cb3ba4a368f1e to your computer and use it in GitHub Desktop.
Save zzzz465/36189fd288c66d90d70cb3ba4a368f1e to your computer and use it in GitHub Desktop.
Pelador request, patching with transpiler.
using System.Collections.Generic;
using Verse;
using RimWorld;
using Harmony;
using System.Reflection;
using System.Linq;
using System.Reflection.Emit;
public class CustomAction
{
public delegate void RefAction<T1, T2, T3>(ref T1 t1, T2 t2, T3 t3);
}
//or use this
//public delegate void RefAction<T1, T2, T3>(ref T1 t1, T2 t2, T3 t3);
public static class Patch_WorkGiver_DoBill
{
static MethodBase GetBillGiverRootCell = AccessTools.Method(typeof(WorkGiver_DoBill), "GetBillGiverRootCell");
static FieldInfo newReleventThingsFieldInfo = AccessTools.Field(typeof(WorkGiver_DoBill), "newRelevantThings");
static CustomAction.RefAction<List<Thing>, Thing, IntVec3> refAction;
static Thing billGiver;
static Pawn pawn;
static IntVec3 rootCell;
public static void DoPatch(HarmonyInstance HMinstance, CustomAction.RefAction<List<Thing>, Thing, IntVec3> refAction)
{
var original = AccessTools.Method(typeof(WorkGiver_DoBill), "<>m__3");
var prefix = AccessTools.Method(typeof(Patch_WorkGiver_DoBill), "Prefix_ResourceGetter");
var transpiler = AccessTools.Method(typeof(Patch_WorkGiver_DoBill), "Transpiler_bracket_m__3");
HMinstance.Patch(original, new HarmonyMethod(prefix), null, new HarmonyMethod(transpiler));
Patch_WorkGiver_DoBill.refAction = refAction;
}
static void Prefix_ResourceGetter(Pawn pawn, Thing billGiver)
{
Patch_WorkGiver_DoBill.billGiver = billGiver;
Patch_WorkGiver_DoBill.pawn = pawn;
}
static void MethodInvoker(ref List<Thing> newReleventThings)
{
var rootCell = (IntVec3)GetBillGiverRootCell.Invoke(null, new object[] { billGiver, pawn });
refAction.Invoke(ref newReleventThings, billGiver, rootCell);
}
static IEnumerable<CodeInstruction> Transpiler_bracket_m__3(IEnumerable<CodeInstruction> instructions)
{
var invokeMethod = AccessTools.Method(typeof(Patch_WorkGiver_DoBill), "MethodInvoker");
var insts = instructions.ToList();
int instsCount = insts.Count;
for(int i = 0; i < instsCount; i++)
{
var inst = insts[i];
if(i > 0 && i < instsCount - 1 && insts[i-1].opcode == OpCodes.Ble && inst.opcode == OpCodes.Ldarg_0 && insts[i+1].operand?.ToString().Contains("<>m__4") == true)
{ // entering line 739, IL, DnSpy
yield return new CodeInstruction(OpCodes.Ldsflda, newReleventThingsFieldInfo);
yield return new CodeInstruction(OpCodes.Call, invokeMethod);
i += 6;
continue; // jump to line 745, callvirt Sort. next invoking line is 746 ldsfld.
}
yield return inst;
}
}
//Patch Example
static void Patch()
{
DoPatch(null, Do_Work);
}
//Method Example
static void Do_Work(ref List<Thing> things, Thing thing, IntVec3 intVec3)
{
//do something... ok?
}
//wrote by madeline#1941
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment