public Initializer(ModContentPack content) : base(content) { Instance = this; HarmonyMain.Initialize(); //Settings.Instance = GetSettings<Settings>(); HarmonyProfilerController.Initialize(); Log.Message($"HarmonyProfiler :: Initialized"); }
public static string AllHarmonyPatchesDump() { StringBuilder sb = new StringBuilder(); sb.AppendLine("===[Harmony Patches]==="); void dumpPatchesInfo(string type, ReadOnlyCollection <Patch> patches) { // Sort patches by harmony execute priority var patchesSorted = patches.ToList().OrderByDescending(x => x.priority).ThenBy(x => x.index); foreach (var p in patchesSorted) { var m = p.PatchMethod; sb.AppendLine($" {type}:{m.ReturnType.Name} {m.GetMethodFullString()} [mod:{p.owner}, prior:{p.priority}, idx:{p.index}]"); foreach (var b in p.before) { sb.AppendLine($" before:{b}"); } foreach (var a in p.after) { sb.AppendLine($" after:{a}"); } } //if (patches.Count > 0) // sb.AppendLine(); } var patchesDic = HarmonyMain.GetPatches(null, false); foreach (var kv in patchesDic) { var patch = kv.Value; if (patch.Owners.Count >= 1) { sb.AppendLine($"{kv.Key.GetMethodFullString()}:(Owners:{patch.Owners.Count}, Prefixes:{patch.Prefixes.Count}, Postfixes:{patch.Postfixes.Count}, Transpilers:{patch.Transpilers.Count})"); dumpPatchesInfo("prefix", patch.Prefixes); dumpPatchesInfo("transpiler", patch.Transpilers); dumpPatchesInfo("postfix", patch.Postfixes); sb.AppendLine(); } } return(sb.ToString()); }
public static void ResetProfiler() { if (!CanUnpatch()) { return; } // Unpatch all foreach (var p in HarmonyMain.GetPatches(new[] { DubId }, false)) { DubInst.Unpatch(p.Key, HarmonyPatchType.All, DubId); } // ApplyPerfomancePatches beforeMainTabs_PatchMe.Invoke(null, null); foreach (var type in GenTypes.AllTypes.Where(x => x.GetAttr("PerformancePatch") != null)) { MethodInfo methodInfo = AccessTools.Method(type, "PerformancePatch"); methodInfo?.Invoke(null, null); } //ResetTabs if (dialogAnalyzer_mainTabs.GetValue(null) is IEnumerable list) { var enumerator = list.GetEnumerator(); while (enumerator.MoveNext()) { // clear dictionary var modes = profileTab_Modes.GetValue(enumerator.Current); modes.GetType().GetMethod("Clear").Invoke(modes, null); } } dialogAnalyzer_PatchedEverything.SetValue(null, false); analyzer_RequestStop.SetValue(null, true); Log.Warning($"Unpatched: {DubId}"); }
public static string CanConflictHarmonyPatchesDump() { StringBuilder sb = new StringBuilder(); sb.AppendLine("===[Harmony Patches Can Conflict]==="); var allPatches = HarmonyMain.GetPatchedMethods(null, false) .GroupBy(x => x.originalMethod) .Select(x => new { method = x.Key, patches = x // sort patches in execution priority. prefixes->transpilers->postfixes .Where(y => y.patchType != PatchType.Postfix) // can be blocked only transpilers or low priority prefixes .OrderBy(y => y.patchType) .ThenByDescending(y => y.harmonyPatch.priority) .ThenBy(y => y.harmonyPatch.index) .ToList() }); bool HasConflictPatches(List <PatchInfo> sortedByExecuteOrder) { for (int i = 0; i < sortedByExecuteOrder.Count; i++) { var p = sortedByExecuteOrder[i]; if (p.patchType == PatchType.Prefix && p.harmonyPatch.PatchMethod.ReturnType == typeof(System.Boolean) && i != sortedByExecuteOrder.Count - 1) { // can block another prefixes, transpilers or postfixes return(true); } if (p.patchType > PatchType.Prefix) { // transpilers and postfixes can't be bool patch return(false); } } return(false); } foreach (var p in allPatches) { if (!HasConflictPatches(p.patches)) { continue; } int owners = p.patches.Select(x => x.harmonyPatch.owner).Distinct().Count(); if (owners <= 1) { continue; } int prefixes = p.patches.Count(x => x.patchType == PatchType.Prefix); int transpilers = p.patches.Count(x => x.patchType == PatchType.Transpiler); int postfixes = p.patches.Count(x => x.patchType == PatchType.Postfix); sb.AppendLine($"{p.method.GetMethodFullString()}:(Owners: {owners} Prefixes:{prefixes}, Postfixes:{postfixes}, Transpilers:{transpilers})"); foreach (var patchInfo in p.patches) { var harmonyPatch = patchInfo.harmonyPatch; var patchMethod = harmonyPatch.PatchMethod; sb.AppendLine($" {patchInfo.patchType} => {patchMethod.ReturnType.Name} {patchMethod.GetMethodFullString()} [mod:{harmonyPatch.owner}, prior:{harmonyPatch.priority}, idx:{harmonyPatch.index}]"); foreach (var b in harmonyPatch.before) { sb.AppendLine($" before:{b}"); } foreach (var a in harmonyPatch.after) { sb.AppendLine($" after:{a}"); } } sb.AppendLine(); } return(sb.ToString()); }