Пример #1
0
 /// <summary>Gets Harmony version for all active Harmony instances</summary>
 /// <param name="currentVersion">[out] The current Harmony version</param>
 /// <returns>A dictionary containing assembly versions keyed by Harmony IDs</returns>
 ///
 public static Dictionary <string, Version> VersionInfo(out Version currentVersion)
 {
     return(PatchProcessor.VersionInfo(out currentVersion));
 }
Пример #2
0
 /// <summary>Gets all patched original methods in the appdomain</summary>
 /// <returns>An enumeration of patched original methods</returns>
 ///
 public static IEnumerable <MethodBase> GetAllPatchedMethods()
 {
     return(PatchProcessor.GetAllPatchedMethods());
 }
Пример #3
0
 /// <summary>Gets patch information for a given original method</summary>
 /// <param name="method">The original method</param>
 /// <returns>The patch information</returns>
 ///
 public static Patches GetPatchInfo(MethodBase method)
 {
     return(PatchProcessor.GetPatchInfo(method));
 }
Пример #4
0
        /// <summary>Unpatches a method</summary>
        /// <param name="original">The original method</param>
        /// <param name="patch">The patch method to remove</param>
        ///
        public void Unpatch(MethodBase original, MethodInfo patch)
        {
            var processor = new PatchProcessor(this, original);

            processor.Unpatch(patch);
        }
Пример #5
0
        /// <summary>Unpatches a method</summary>
        /// <param name="original">The original method</param>
        /// <param name="type">The patch type</param>
        /// <param name="harmonyID">The optional Harmony ID to restrict unpatching to a specific instance</param>
        ///
        public void Unpatch(MethodBase original, HarmonyPatchType type, string harmonyID = null)
        {
            var processor = new PatchProcessor(this, original);

            processor.Unpatch(type, harmonyID);
        }
Пример #6
0
        /// <summary>
        /// Applies all patches specified in the type.
        /// </summary>
        /// <param name="type">The type to scan.</param>
        public void PatchAll(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }
            foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
            {
                var patchAttributeMethods = HarmonyMethodExtensions.GetFromMethod(method);
                if (patchAttributeMethods != null && patchAttributeMethods.Any())
                {
                    var attributes = method.GetCustomAttributes(true);

                    var combinedInfo = HarmonyMethod.Merge(patchAttributeMethods);

                    bool IsMethodComplete(HarmonyMethod m)
                    {
                        return(m.declaringType != null &&
                               (m.methodName != null || m.methodType == MethodType.Constructor || m.methodType == MethodType.StaticConstructor));
                    }

                    var completeMethods = patchAttributeMethods.Where(IsMethodComplete).ToList();

                    if (patchAttributeMethods.All(x => x.declaringType != combinedInfo.declaringType && x.methodName != combinedInfo.methodName))
                    {
                        completeMethods.Add(combinedInfo);
                    }

                    var originalMethods = new List <MethodBase>();

                    foreach (var methodToPatch in completeMethods)
                    {
                        foreach (var index in attributes.OfType <ParameterByRefAttribute>().SelectMany(x => x.ParameterIndices))
                        {
                            if (!methodToPatch.argumentTypes[index].IsByRef)
                            {
                                methodToPatch.argumentTypes[index] = methodToPatch.argumentTypes[index].MakeByRefType();
                            }
                        }

                        if (!methodToPatch.methodType.HasValue)
                        {
                            methodToPatch.methodType = MethodType.Normal;
                        }

                        if (methodToPatch.method == null)
                        {
                            methodToPatch.method = method;
                        }

                        var originalMethod = PatchProcessor.GetOriginalMethod(methodToPatch);

                        if (originalMethod != null)
                        {
                            originalMethods.Add(originalMethod);
                        }
                    }

                    var processor = new PatchProcessor(this);

                    foreach (var originalMethod in originalMethods)
                    {
                        processor.AddOriginal(originalMethod);
                    }

                    if (attributes.Any(x => x is HarmonyPrefix))
                    {
                        processor.AddPrefix(new HarmonyMethod(method));
                    }

                    if (attributes.Any(x => x is HarmonyTranspiler))
                    {
                        processor.AddTranspiler(new HarmonyMethod(method));
                    }

                    if (attributes.Any(x => x is HarmonyPostfix))
                    {
                        processor.AddPostfix(new HarmonyMethod(method));
                    }

                    if (attributes.Any(x => x is HarmonyFinalizer))
                    {
                        processor.AddFinalizer(new HarmonyMethod(method));
                    }

                    processor.Patch();
                }
                else
                {
                    // Only check when logging warnings
                    if ((Logger.ChannelFilter & Logger.LogChannel.Warn) != 0)
                    {
                        if (method.GetCustomAttributes(typeof(HarmonyAttribute), true).Any())
                        {
                            Logger.LogText(Logger.LogChannel.Warn, "Method " + method.FullDescription() + " has an invalid combination of Harmony attributes and will be ignored");
                        }
                    }
                }
            }
        }