private static IEnumerable <CodeInstruction> Transpiler(MethodBase __originalMethod, IEnumerable <CodeInstruction> codeInstructions) { var enumerable = codeInstructions.ToList(); try { List <CodeInstruction> instructions = enumerable; for (int i = 0; i < instructions.Count; i++) { if (!IsFunctionCall(instructions[i].opcode)) { continue; } if (!(instructions[i].operand is MethodInfo meth)) { continue; } // Check for constrained if (i != 0 && instructions[i - 1].opcode == OpCodes.Constrained) { continue; } // Make sure it is not an analyzer profiling method if (meth.DeclaringType.FullName.Contains("Analyzer.Profiling")) { continue; } var key = Utility.GetMethodKey(meth); var index = MethodInfoCache.AddMethod(key, meth); var inst = MethodTransplanting.ReplaceMethodInstruction( instructions[i], key, GUIController.types[__originalMethod.DeclaringType + ":" + __originalMethod.Name + "-int"], index); instructions[i] = inst; } return(instructions); } catch (Exception e) { #if DEBUG ThreadSafeLogger.Error($"Failed to patch the internal method {__originalMethod.DeclaringType.FullName}:{__originalMethod.Name}, failed with the error " + e.Message); #else if (Settings.verboseLogging) { ThreadSafeLogger.Warning($"Failed to patch the internal method {__originalMethod.DeclaringType.FullName}:{__originalMethod.Name}, failed with the error " + e.Message); } #endif return(enumerable); } }
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); }
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); var index = MethodInfoCache.AddMethod(key, __originalMethod); foreach (var thing in insts.changeSet) { // We only want added methods if (thing.change != ChangeType.Added) { continue; } if (!Utility.ValidCallInstruction(thing.value, null, out var meth, out _)) { continue; } if (!(meth is MethodInfo)) { continue; } // swap our instruction var replaceInstruction = MethodTransplanting.ReplaceMethodInstruction( thing.value, key, typeof(H_HarmonyTranspilersInternalMethods), index); modInstList[thing.rIndex] = replaceInstruction; } return(modInstList); }
private static IEnumerable <CodeInstruction> Transpiler(MethodBase __originalMethod, IEnumerable <CodeInstruction> codeInstructions) { try { var instructions = codeInstructions.ToList(); for (int i = 0; i < instructions.Count; i++) { if (!Utility.ValidCallInstruction(instructions[i], i == 0 ? null : instructions[i - 1], out var meth, out var key)) { continue; } var index = MethodInfoCache.AddMethod(key, meth); var inst = MethodTransplanting.ReplaceMethodInstruction( instructions[i], key, GUIController.types[__originalMethod.DeclaringType + ":" + __originalMethod.Name + "-int"], index); instructions[i] = inst; } return(instructions); } catch (Exception e) { #if DEBUG ThreadSafeLogger.ReportException(e, $"Failed to patch the methods inside {Utility.GetSignature(__originalMethod, false)}"); #else if (Settings.verboseLogging) { ThreadSafeLogger.ReportException(e, $"Failed to patch the methods inside {Utility.GetSignature(__originalMethod, false)}"); } #endif return(codeInstructions); } }