public static void Clicked(Profiler prof, ProfileLog log) { if (Input.GetKey(KeyCode.LeftControl)) { if (log.Meth == null) { Messages.Message("Null method", MessageTypeDefOf.NegativeEvent, false); return; } var patches = Harmony.GetAllPatchedMethods().ToList(); // Patches patchInfo = Harmony.GetPatchInfo(log.Meth); foreach (var methodBase in patches) { var infos = Harmony.GetPatchInfo(methodBase); foreach (var infosPrefix in infos.Prefixes) { if (infosPrefix.PatchMethod == log.Meth) { Analyzer.harmony.Unpatch(methodBase, HarmonyPatchType.All, "*"); Messages.Message("Unpatched prefixes", MessageTypeDefOf.TaskCompletion, false); } } foreach (var infosPostfixesx in infos.Postfixes) { if (infosPostfixesx.PatchMethod == log.Meth) { Analyzer.harmony.Unpatch(methodBase, HarmonyPatchType.All, "*"); Messages.Message("Unpatched postfixes", MessageTypeDefOf.TaskCompletion, false); } } } } }
private void RefreshListOfPatchOwners(string modId, bool reset = true) { if (reset || _modIdsToColor == null) { _modIdsToColor = new Dictionary <string, string>(); } var patches = Harmony.GetAllPatchedMethods().SelectMany(method => { Patches patchInfo = Harmony.GetPatchInfo(method); return(patchInfo.Prefixes.Concat(patchInfo.Transpilers).Concat(patchInfo.Postfixes)); }); var owners = patches.Select(patchInfo => patchInfo.owner).Distinct().OrderBy(owner => owner); float hue = 0.0f; foreach (var owner in owners) { if (!_modIdsToColor.ContainsKey(owner)) { var color = UnityEngine.Random.ColorHSV( hue, hue, 0.25f, .75f, 0.75f, 1f ); _modIdsToColor[owner] = ColorUtility.ToHtmlStringRGBA(color); hue = (hue + 0.1f) % 1.0f; } } }
public static void ProfilePatch() { var patches = Harmony.GetAllPatchedMethods().ToList(); var filteredTranspilers = patches .Where(m => Harmony.GetPatchInfo(m).Transpilers.Any(p => Utility.IsNotAnalyzerPatch(p.owner) && !TranspilerMethodUtility.PatchedMeths.Contains(m))) .ToList(); TranspilerMethodUtility.PatchedMeths.AddRange(filteredTranspilers); foreach (var meth in filteredTranspilers) { try { Modbase.Harmony.Patch(meth, transpiler: TranspilerMethodUtility.TranspilerProfiler); } catch (Exception e) { #if DEBUG ThreadSafeLogger.ReportException(e, $"[Analyzer] Failed to patch transpiler {Utility.GetSignature(meth, false)}"); #endif #if NDEBUG if (Settings.verboseLogging) { ThreadSafeLogger.ReportException(e, $"[Analyzer] Failed to patch transpiler {Utility.GetSignature(meth, false)}"); } #endif } } }
private void RefreshListOfPatchOwners(string modId, bool reset = true) { if (reset || _modIdsToColor == null) { _modIdsToColor = new Dictionary <string, string>(); } var rgbaValues = Enum.GetValues(typeof(RGBA)); var rgbaCount = rgbaValues.Length; foreach (Patch patch in Harmony.GetAllPatchedMethods().SelectMany(method => { Patches patches = Harmony.GetPatchInfo(method); return(patches.Prefixes.Concat(patches.Transpilers).Concat(patches.Postfixes)); })) { if (!_modIdsToColor.ContainsKey(patch.owner)) { var rgbaIndex = Math.Abs(patch.owner.GetHashCode() % rgbaCount); RGBA color = (RGBA)rgbaValues.GetValue(rgbaIndex); var colorString = color.ToHtmlString(); _modIdsToColor[patch.owner] = colorString; //_modIdsToColor[patch.owner] = ColorUtility.ToHtmlStringRGBA(UnityEngine.Random.ColorHSV(0f, 1f, 0.25f, 1f, 0.75f, 1f)); } } }
private static void UnpatchMethodFull(MethodInfo method, bool display = true) { foreach (var methodBase in Harmony.GetAllPatchedMethods()) { var infos = Harmony.GetPatchInfo(methodBase); foreach (var infosPrefix in infos.Prefixes) { if (infosPrefix.PatchMethod == method) { Analyzer.harmony.Unpatch(methodBase, method); return; } } foreach (var infosPostfixesx in infos.Postfixes) { if (infosPostfixesx.PatchMethod == method) { Analyzer.harmony.Unpatch(methodBase, method); return; } } } if (display) { Warn("Failed to locate method to unpatch"); } }
public static void ProfilePatch() { var go = new HarmonyMethod(typeof(H_HarmonyTranspilers), nameof(Prefix)); var biff = new HarmonyMethod(typeof(H_HarmonyTranspilers), nameof(Postfix)); var trans = new HarmonyMethod(typeof(H_HarmonyTranspilers), nameof(Transpiler)); int c = 0; int p = 0; var patches = Harmony.GetAllPatchedMethods().ToList(); foreach (var mode in patches) { try { c++; Patches patchInfo = Harmony.GetPatchInfo(mode); var pilers = patchInfo.Transpilers; if (!pilers.NullOrEmpty()) { p++; if (pilers.Any(x => x.owner != Analyzer.harmony.Id && x.owner != Analyzer.perfharmony.Id) && !PatchedMeths.Contains(mode)) { PatchedMeths.Add(mode); Analyzer.harmony.Patch(mode, go, biff); } } } catch (Exception) { } } }
public static void ProfilePatch() { var patches = Harmony.GetAllPatchedMethods().ToList(); var filteredTranspilers = patches .Where(m => Harmony.GetPatchInfo(m).Transpilers.Any(p => Utility.IsNotAnalyzerPatch(p.owner) && !TranspilerMethodUtility.PatchedMeths.Contains(m))) .ToList(); TranspilerMethodUtility.PatchedMeths.AddRange(filteredTranspilers); foreach (var meth in filteredTranspilers) { try { Modbase.Harmony.Patch(meth, transpiler: TranspilerMethodUtility.TranspilerProfiler); } catch (Exception e) { #if DEBUG ThreadSafeLogger.Error($"[Analyzer] Failed to patch transpiler, failed with the message {e.Message}"); #endif #if NDEBUG if (Settings.verboseLogging) { ThreadSafeLogger.Error($"[Analyzer] Failed to patch transpiler {meth.DeclaringType.FullName + ":" + meth.Name}, failed with the message {e.Message}"); } #endif } } }
public static bool HarmonyInstance_GetPatchedMethods_Prefix(string ___id, out IEnumerable <MethodBase> __result) { #if DEBUG UnityEngine.Debug.Log($"GetPatchedMethods (HarmonyId: {___id})"); #endif __result = Harmony.GetAllPatchedMethods(); return(false); }
private void RefreshPatchInfoOfAllMods(string modId) { _patches = new Dictionary <MethodBase, List <Patch> >(); foreach (MethodBase method in Harmony.GetAllPatchedMethods()) { _patches.Add(method, GetSortedPatches(method).ToList()); } }
/// <summary> /// Produces a human-readable list of all methods patched by all Harmony instances and their respective patches. /// </summary> public static string DescribeAllPatchedMethods() { try { return(DescribePatchedMethodsList(Harmony.GetAllPatchedMethods())); } catch (Exception e) { return("Could not retrieve patched methods from the Harmony library:\n" + e); } }
private static IEnumerable <(string owner, IEnumerable <MethodBase> methods)> EnumerateObsoleteMethodPatchOwners() { return(Harmony.GetAllPatchedMethods() .Select(method => (method, info: Harmony.GetPatchInfo(method))) .Where(pair => HasActivePatches(pair.info) && pair.method.HasAttribute <ObsoleteAttribute>()) .SelectMany(pair => pair.info.Owners, (pair, owner) => (owner, pair.method)) .GroupBy(pair => pair.owner, pair => pair.method) .Select(grp => (grp.Key, grp as IEnumerable <MethodBase>))); }
internal static void Reenable() { if (!Config.Extras.HarmonyInlining) { return; } _ = Parallel.ForEach(Harmony.GetAllPatchedMethods(), EnableInlining); }
/// <summary> /// Get collection [method, patches] /// </summary> /// <param name="owners">filter patches by owners or null for get all patches</param> /// <param name="skipGenericMethods">include generic methods</param> /// <returns></returns> public static Dictionary <MethodBase, Patches> GetPatches(string[] owners, bool skipGenericMethods) { var patches = Harmony.GetAllPatchedMethods() .Where(method => !skipGenericMethods || !method.DeclaringType.IsGenericType) .Select(method => new { method, patches = Harmony.GetPatchInfo(method) }); return(owners == null ? patches.ToDictionary(x => x.method, y => y.patches) : patches.Where(patch => patch.patches.Owners.Any(x => owners.Any(x.Equals))) .ToDictionary(x => x.method, y => y.patches)); }
public static unsafe void PrintInlined() { foreach (var m in Harmony.GetAllPatchedMethods()) { // method->inline_info if ((*(byte *)(m.MethodHandle.Value + 32) & 1) == 1) { Log.Warning($"Mono inlined {m.FullDescription()} {*(byte*)(m.MethodHandle.Value + 32) & 1} {*((ushort*)(m.MethodHandle.Value) + 1) & (ushort)MethodImplOptions.NoInlining}"); } } }
public static IEnumerable <MethodInfo> GetPatchMethods() { foreach (MethodBase mode in Harmony.GetAllPatchedMethods().ToList()) { Patches patchInfo = Harmony.GetPatchInfo(mode); foreach (var fix in patchInfo.Prefixes.Concat(patchInfo.Postfixes).Where(f => Utility.IsNotAnalyzerPatch(f.owner))) { yield return(fix.PatchMethod); } } }
public static void CheckAndApplyCleaveCompatibility() { var methodBases = Harmony.GetAllPatchedMethods(); foreach (var method in methodBases) { if (Harmony.GetPatchInfo(method).Owners.Contains("xorberax.cutthrougheveryone")) { ApplyCompatibility(); } } }
public static string getPotentialModConflicts() { string modsText = ""; IEnumerable <MethodBase> originalMethods = Harmony.GetAllPatchedMethods(); foreach (MethodBase originalMethod in originalMethods) { Patches patches = Harmony.GetPatchInfo(originalMethod); if (patches is null) { } else { bool isRimThreadedPrefixed = false; foreach (Patch patch in patches.Prefixes) { if (patch.owner.Equals("majorhoff.rimthreaded") && !RimThreadedHarmony.nonDestructivePrefixes.Contains(patch.PatchMethod) && (patches.Prefixes.Count > 1 || patches.Postfixes.Count > 0 || patches.Transpilers.Count > 0)) { isRimThreadedPrefixed = true; modsText += "\n ---Patch method: " + patch.PatchMethod.DeclaringType?.FullName + " " + patch.PatchMethod + "---\n"; modsText += " RimThreaded priority: " + patch.priority + "\n"; break; } } if (isRimThreadedPrefixed) { foreach (Patch patch in patches.Prefixes) { if (!patch.owner.Equals("majorhoff.rimthreaded")) { //Settings.modsText += "method: " + patch.PatchMethod + " - "; modsText += " owner: " + patch.owner + " - "; modsText += " FullName: " + patch.PatchMethod.DeclaringType?.FullName + "\n"; } } foreach (Patch patch in patches.Postfixes) { //Settings.modsText += "method: " + patch.PatchMethod + " - "; modsText += " owner: " + patch.owner + " - "; modsText += " FullName: " + patch.PatchMethod.DeclaringType?.FullName + "\n"; } foreach (Patch patch in patches.Transpilers) { //Settings.modsText += "method: " + patch.PatchMethod + " - "; modsText += " owner: " + patch.owner + " - "; modsText += " FullName: " + patch.PatchMethod.DeclaringType?.FullName + "\n"; } } } } return(modsText); }
private void RefreshPatchInfoOfPotentialConflict(string modId) { _patches = new Dictionary <MethodBase, List <Patch> >(); foreach (MethodBase method in Harmony.GetAllPatchedMethods()) { IEnumerable <Patch> patches = GetSortedPatches(method); var owners = patches.Select(patch => patch.owner).Distinct().ToHashSet(); if (owners.Count > 1 && (_modID == null || owners.Contains(_modID))) { _patches.Add(method, patches.ToList()); } } }
private void RefreshPatchInfoOfSelected(string modId) { _patches = new Dictionary <MethodBase, List <Patch> >(); foreach (MethodBase method in Harmony.GetAllPatchedMethods()) { IEnumerable <Patch> patches = GetSortedPatches(method).Where(patch => patch.owner == _modID); if (patches.Any()) { _patches.Add(method, patches.ToList()); } } }
public static IEnumerable <MethodInfo> GetPatchMethods() { var patches = Harmony.GetAllPatchedMethods().ToList(); var filteredTranspilers = patches.Where(m => Harmony.GetPatchInfo(m).Transpilers.Any(p => Utility.IsNotAnalyzerPatch(p.owner))).ToList(); foreach (var filteredTranspiler in filteredTranspilers) { yield return(filteredTranspiler as MethodInfo); // Modbase.Harmony.Patch(AccessTools.Method(typeof(DynamicDrawManager), nameof(DynamicDrawManager.DrawDynamicThings)), prefix: new HarmonyMethod(typeof(H_DrawDynamicThings), "Prefix")); } // yield return AccessTools.Method(typeof(PawnRenderer), nameof(PawnRenderer.RenderPawnAt), new Type[] { typeof(Vector3), typeof(RotDrawMode), typeof(bool), typeof(bool) }); }
private void RefreshPatchInfoOfPotentialConflict(string modId) { _patches = new Dictionary <MethodBase, List <Patch> >(); Harmony harmonyInstance = new Harmony(_modId); foreach (MethodBase method in Harmony.GetAllPatchedMethods()) { IEnumerable <Patch> patches = GetSortedPatches(harmonyInstance, method); if (patches.Any(patch => patch.owner == _modId) && patches.Any(patch => patch.owner != _modId)) { _patches.Add(method, patches.ToList()); } } }
public static HashSet <string> GetAllHarmonyInstances() { HashSet <string> owners = new HashSet <string>(); var patched = Harmony.GetAllPatchedMethods(); foreach (var method in patched) { var patchInfo = Harmony.GetPatchInfo(method); foreach (var owner in patchInfo.Owners) { if (!owner.Equals(Id)) { owners.Add(owner); } } } return(owners); }
public static void CheckForShoulderCam() { if (CamCompatibilityCheckComplete == false) { CamCompatibilityCheckComplete = false; var methodBases = Harmony.GetAllPatchedMethods(); foreach (var method in methodBases) { if (Harmony.GetPatchInfo(method).Owners.Contains("xorberax.shouldercam")) { XorbShoulderCamDetected = true; } } CamCompatibilityCheckComplete = true; } }
public static void UnpatchMethod(MethodInfo method) { foreach (MethodBase methodBase in Harmony.GetAllPatchedMethods()) { HarmonyLib.Patches infos = Harmony.GetPatchInfo(methodBase); var allPatches = infos.Prefixes.Concat(infos.Postfixes, infos.Transpilers, infos.Finalizers); if (!allPatches.Any(patch => patch.PatchMethod == method)) { continue; } Modbase.Harmony.Unpatch(methodBase, method); return; } Warn("Failed to locate method to unpatch"); }
private void RefreshListOfPatchOwners(string modId, bool reset = true) { if (reset || _modIdsToColor == null) { _modIdsToColor = new Dictionary <string, string>(); } foreach (Patch patch in Harmony.GetAllPatchedMethods().SelectMany(method => { Patches patches = Harmony.GetPatchInfo(method); return(patches.Prefixes.Concat(patches.Transpilers).Concat(patches.Postfixes)); })) { if (!_modIdsToColor.ContainsKey(patch.owner)) { _modIdsToColor[patch.owner] = ColorUtility.ToHtmlStringRGBA(UnityEngine.Random.ColorHSV(0f, 1f, 0.25f, 1f, 0.75f, 1f)); } } }
public static void CheckHarmonyPatchesForPotentialWarnings() { IEnumerable <(MethodBase, HarmonyLib.Patches)> patchList = Harmony.GetAllPatchedMethods().Select(mb => (mb, Harmony.GetPatchInfo(mb))).Where(mp => HasActivePatches(mp.Item2)); StringBuilder builderObsolete = new StringBuilder($"Potentially outdated mods for {typeof(Log).Assembly.GetName().Version}. Please alert the mod authors of the mods in the following list that they may have to update the patches for their mods and include the following information.\n"); bool printObsolete = false; foreach (IGrouping <string, (string owner, MethodBase)> owners in patchList.Where(mp => mp.Item1.HasAttribute <ObsoleteAttribute>()) .SelectMany(mp => mp.Item2.Prefixes.Concat(mp.Item2.Postfixes).Concat(mp.Item2.Transpilers) .Select(p => (p.owner, mp.Item1))).GroupBy(p => p.owner)) { builderObsolete.AppendLine($"Mod: {owners.Key}: {string.Join(" | ", owners.Select(mb => mb.Item2.Name).Distinct())}"); printObsolete = true; } if (printObsolete) { HugsLibController.Logger.Error(builderObsolete.ToString()); } }
/// <summary> /// Compiles the patched method list from Harmony. /// </summary> internal static void CompileModPatches() { var mods = Global.Instance.modManager?.mods; if (mods != null) { var methodsByID = new Dictionary <string, LoadedModData>(); // Index the mods list by Harmony ID foreach (var mod in mods) { var data = mod.loaded_mod_data; var h = data?.harmony; if (h != null) { // Remove anything that was loaded before us data.patched_methods?.Clear(); data.patched_methods = new HashSet <MethodBase>(); if (h != null && !string.IsNullOrEmpty(h.Id)) { methodsByID[h.Id] = data; } } } // Match up all patched methods to the mod itself foreach (var method in Harmony.GetAllPatchedMethods()) { var patchInfo = Harmony.GetPatchInfo(method); var owners = patchInfo?.Owners; if (owners != null) { foreach (string owner in owners) { if (methodsByID.TryGetValue(owner, out LoadedModData data)) { data.patched_methods.Add(method); } } } } } }
public static void ProfilePatch() { var go = new HarmonyMethod(typeof(H_HarmonyPatches), nameof(Prefix)); var biff = new HarmonyMethod(typeof(H_HarmonyPatches), nameof(Postfix)); var patches = Harmony.GetAllPatchedMethods().ToList(); foreach (var mode in patches) { Patches patchInfo = Harmony.GetPatchInfo(mode); foreach (var fix in patchInfo.Prefixes) { try { if (Analyzer.harmony.Id != fix.owner && Analyzer.perfharmony.Id != fix.owner && !PatchedPres.Contains(fix)) { PatchedPres.Add(fix); Analyzer.harmony.Patch(fix.PatchMethod, go, biff); } } catch (Exception) { } } foreach (var fix in patchInfo.Postfixes) { try { if (Analyzer.harmony.Id != fix.owner && Analyzer.perfharmony.Id != fix.owner && !PatchedPosts.Contains(fix)) { PatchedPosts.Add(fix); Analyzer.harmony.Patch(fix.PatchMethod, go, biff); } } catch (Exception) { } } } }
public static IEnumerable <MethodInfo> GetPatchMethods() { var patches = Harmony.GetAllPatchedMethods().ToList(); foreach (var patch in patches) { HarmonyLib.Patches p = null; try { p = Harmony.GetPatchInfo(patch); } catch (Exception e) { ThreadSafeLogger.ReportException(e, $"Failed to get patch info for {Utility.GetSignature(patch)}"); continue; } if (patch is MethodInfo info && p.Transpilers.Any(p => Utility.IsNotAnalyzerPatch(p.owner))) { yield return(info); } } }
static void Main_Example() { // <create> var harmony = new Harmony("com.company.project.product"); // </create> // <debug> Harmony.DEBUG = true; // </debug> // <log> FileLog.Log("something"); // or buffered: FileLog.LogBuffered("A"); FileLog.LogBuffered("B"); FileLog.FlushBuffer(); /* don't forget to flush */ // </log> // <patch_annotation> var assembly = Assembly.GetExecutingAssembly(); harmony.PatchAll(assembly); // or implying current assembly: harmony.PatchAll(); // </patch_annotation> void PatchManual() { // <patch_manual> // add null checks to the following lines, they are omitted for clarity var original = typeof(TheClass).GetMethod("TheMethod"); var prefix = typeof(MyPatchClass1).GetMethod("SomeMethod"); var postfix = typeof(MyPatchClass2).GetMethod("SomeMethod"); harmony.Patch(original, new HarmonyMethod(prefix), new HarmonyMethod(postfix)); // You can use named arguments to specify certain patch types only: harmony.Patch(original, postfix: new HarmonyMethod(postfix)); harmony.Patch(original, prefix: new HarmonyMethod(prefix), transpiler: new HarmonyMethod(transpiler)); // </patch_manual> // <patch_method> var harmonyPostfix = new HarmonyMethod(postfix) { priority = Priority.Low, before = new[] { "that.other.harmony.user" } }; // </patch_method> } PatchManual(); // <patch_getall> var originalMethods = Harmony.GetAllPatchedMethods(); foreach (var method in originalMethods) { } // </patch_getall> // <patch_get> var myOriginalMethods = harmony.GetPatchedMethods(); foreach (var method in myOriginalMethods) { } // </patch_get> void PatchInfo() { // <patch_info> // get the MethodBase of the original var original = typeof(TheClass).GetMethod("TheMethod"); // retrieve all patches var patches = Harmony.GetPatchInfo(original); if (patches is null) { return; // not patched } // get a summary of all different Harmony ids involved FileLog.Log("all owners: " + patches.Owners); // get info about all Prefixes/Postfixes/Transpilers foreach (var patch in patches.Prefixes) { FileLog.Log("index: " + patch.index); FileLog.Log("owner: " + patch.owner); FileLog.Log("patch method: " + patch.PatchMethod); FileLog.Log("priority: " + patch.priority); FileLog.Log("before: " + patch.before); FileLog.Log("after: " + patch.after); } // </patch_info> } PatchInfo(); // <patch_has> if (Harmony.HasAnyPatches("their.harmony.id")) { } // </patch_has> // <version> var dict = Harmony.VersionInfo(out var myVersion); FileLog.Log("My version: " + myVersion); foreach (var entry in dict) { var id = entry.Key; var version = entry.Value; FileLog.Log("Mod " + id + " uses Harmony version " + version); } // </version> }