private static IEnumerable <CodeInstruction> Transpiler(MethodBase __originalMethod, IEnumerable <CodeInstruction> instructions) { var inst = PatchProcessor.GetOriginalInstructions(__originalMethod); var modInstList = instructions.ToList(); var insts = new Myers <CodeInstruction>(inst.ToArray(), modInstList.ToArray(), methComparer); insts.Compute(); var key = Utility.GetMethodKey(__originalMethod as MethodInfo); var index = MethodInfoCache.AddMethod(key, __originalMethod as MethodInfo); foreach (var thing in insts.changeSet) { // We only want added methods if (thing.change != ChangeType.Added) { continue; } if (!InternalMethodUtility.IsFunctionCall(thing.value.opcode) || !(thing.value.operand is MethodInfo meth)) { continue; } // swap our instruction var replaceInstruction = MethodTransplanting.ReplaceMethodInstruction( thing.value, key, typeof(H_HarmonyTranspilersInternalMethods), index); // Find the place it was in our method, and replace the instruction (Optimisation Opportunity to improve this) for (var i = 0; i < modInstList.Count; i++) { var instruction = modInstList[i]; if (!InternalMethodUtility.IsFunctionCall(instruction.opcode)) { continue; } if (!(instruction.operand is MethodInfo info) || info.Name != meth.Name) { continue; } if (instruction != replaceInstruction) { modInstList[i] = replaceInstruction; } break; } } return(modInstList); }
// Functions primarily to check if two function call CodeInstructions are the same. public override bool Equals(CodeInstruction b1, CodeInstruction b2) { if (b1.opcode != b2.opcode) { return(false); } if (InternalMethodUtility.IsFunctionCall(b1.opcode)) { try { return(((MethodInfo)b1.operand).Name == ((MethodInfo)b2.operand).Name); } catch { } } return(b1.operand == b2.operand); }