예제 #1
0
        /// <summary>Unpatches patches of a given type and/or Harmony ID</summary>
        /// <param name="type">The <see cref="HarmonyPatchType"/> patch type</param>
        /// <param name="harmonyID">Harmony ID or <c>*</c> for any</param>
        /// <returns>A <see cref="PatchProcessor"/> for chaining calls</returns>
        ///
        public PatchProcessor Unpatch(HarmonyPatchType type, string harmonyID)
        {
            lock (locker)
            {
                var patchInfo = HarmonySharedState.GetPatchInfo(original);
                if (patchInfo == null)
                {
                    patchInfo = new PatchInfo();
                }

                if (type == HarmonyPatchType.All || type == HarmonyPatchType.Prefix)
                {
                    PatchFunctions.RemovePrefix(patchInfo, harmonyID);
                }
                if (type == HarmonyPatchType.All || type == HarmonyPatchType.Postfix)
                {
                    PatchFunctions.RemovePostfix(patchInfo, harmonyID);
                }
                if (type == HarmonyPatchType.All || type == HarmonyPatchType.Transpiler)
                {
                    PatchFunctions.RemoveTranspiler(patchInfo, harmonyID);
                }
                if (type == HarmonyPatchType.All || type == HarmonyPatchType.Finalizer)
                {
                    PatchFunctions.RemoveFinalizer(patchInfo, harmonyID);
                }
                _ = PatchFunctions.UpdateWrapper(original, patchInfo);

                HarmonySharedState.UpdatePatchInfo(original, patchInfo);
                return(this);
            }
        }
예제 #2
0
        /// <summary>Unpatches patches of a given type and/or Harmony ID</summary>
        /// <param name="type">The <see cref="HarmonyPatchType"/> patch type</param>
        /// <param name="harmonyID">Harmony ID or <c>*</c> for any</param>
        /// <returns>A <see cref="PatchProcessor"/> for chaining calls</returns>
        ///
        public PatchProcessor Unpatch(HarmonyPatchType type, string harmonyID)
        {
            lock (locker)
            {
                var patchInfo = original.ToPatchInfo();

                if (type == HarmonyPatchType.All || type == HarmonyPatchType.Prefix)
                {
                    patchInfo.RemovePrefix(harmonyID);
                }
                if (type == HarmonyPatchType.All || type == HarmonyPatchType.Postfix)
                {
                    patchInfo.RemovePostfix(harmonyID);
                }
                if (type == HarmonyPatchType.All || type == HarmonyPatchType.Transpiler)
                {
                    patchInfo.RemoveTranspiler(harmonyID);
                }
                if (type == HarmonyPatchType.All || type == HarmonyPatchType.Finalizer)
                {
                    patchInfo.RemoveFinalizer(harmonyID);
                }
                if (type == HarmonyPatchType.All || type == HarmonyPatchType.ILManipulator)
                {
                    patchInfo.RemoveILManipulator(harmonyID);
                }
                var replacement = PatchFunctions.UpdateWrapper(original, patchInfo);

                PatchManager.AddReplacementOriginal(original, replacement);
                return(this);
            }
        }
예제 #3
0
        /// <summary>Applies all registered patches</summary>
        /// <returns>The generated replacement method</returns>
        ///
        public MethodInfo Patch()
        {
            if (original == null)
            {
                throw new NullReferenceException($"Null method for {instance.Id}");
            }

            if (original.IsDeclaredMember() == false)
            {
                var declaredMember = original.GetDeclaredMember();
                throw new ArgumentException($"You can only patch implemented methods/constructors. Path the declared method {declaredMember.FullDescription()} instead.");
            }

            lock (locker)
            {
                var patchInfo = HarmonySharedState.GetPatchInfo(original);
                if (patchInfo == null)
                {
                    patchInfo = new PatchInfo();
                }

                PatchFunctions.AddPrefix(patchInfo, instance.Id, prefix);
                PatchFunctions.AddPostfix(patchInfo, instance.Id, postfix);
                PatchFunctions.AddTranspiler(patchInfo, instance.Id, transpiler);
                PatchFunctions.AddFinalizer(patchInfo, instance.Id, finalizer);
                var replacement = PatchFunctions.UpdateWrapper(original, patchInfo);

                HarmonySharedState.UpdatePatchInfo(original, patchInfo);
                return(replacement);
            }
        }
예제 #4
0
        void ProcessPatchJob(PatchJobs <MethodInfo> .Job job)
        {
            MethodInfo replacement = default;

            var       individualPrepareResult = RunMethod <HarmonyPrepare, bool>(true, false, null, job.original);
            Exception exception = null;

            if (individualPrepareResult)
            {
                lock (PatchProcessor.locker)
                {
                    try
                    {
                        var patchInfo = HarmonySharedState.GetPatchInfo(job.original) ?? new PatchInfo();

                        patchInfo.AddPrefixes(instance.Id, job.prefixes.ToArray());
                        patchInfo.AddPostfixes(instance.Id, job.postfixes.ToArray());
                        patchInfo.AddTranspilers(instance.Id, job.transpilers.ToArray());
                        patchInfo.AddFinalizers(instance.Id, job.finalizers.ToArray());

                        replacement = PatchFunctions.UpdateWrapper(job.original, patchInfo);
                        HarmonySharedState.UpdatePatchInfo(job.original, replacement, patchInfo);
                    }
                    catch (Exception ex)
                    {
                        exception = ex;
                    }
                }
            }
            RunMethod <HarmonyCleanup>(ref exception, job.original, exception);
            ReportException(exception, job.original);
            job.replacement = replacement;
        }
예제 #5
0
        /// <summary>Applies all registered patches</summary>
        /// <returns>The generated replacement method</returns>
        ///
        public MethodInfo Patch()
        {
            if (original is null)
            {
                throw new NullReferenceException($"Null method for {instance.Id}");
            }

            if (original.IsDeclaredMember() is false)
            {
                Logger.Log(Logger.LogChannel.Warn, () => $"{instance.Id}: You should only patch implemented methods/constructors to avoid issues. Patch the declared method {original.GetDeclaredMember().FullDescription()} instead of {original.FullDescription()}.");
            }

            lock (locker)
            {
                var patchInfo = original.ToPatchInfo();

                patchInfo.AddPrefixes(instance.Id, prefix);
                patchInfo.AddPostfixes(instance.Id, postfix);
                patchInfo.AddTranspilers(instance.Id, transpiler);
                patchInfo.AddFinalizers(instance.Id, finalizer);
                patchInfo.AddILManipulators(instance.Id, ilmanipulator);

                var replacement = PatchFunctions.UpdateWrapper(original, patchInfo);
                PatchManager.AddReplacementOriginal(original, replacement);
                return(replacement);
            }
        }
예제 #6
0
        /// <summary>Applies the patch</summary>
        /// <returns>A list of all created dynamic methods</returns>
        ///
        public List <DynamicMethod> Patch()
        {
            lock (locker)
            {
                var dynamicMethods = new List <DynamicMethod>();
                foreach (var original in originals)
                {
                    if (original == null)
                    {
                        throw new NullReferenceException("Null method for " + instance.Id);
                    }

                    var individualPrepareResult = RunMethod <HarmonyPrepare, bool>(true, original);
                    if (individualPrepareResult)
                    {
                        var patchInfo = HarmonySharedState.GetPatchInfo(original);
                        if (patchInfo == null)
                        {
                            patchInfo = new PatchInfo();
                        }

                        PatchFunctions.AddPrefix(patchInfo, instance.Id, prefix);
                        PatchFunctions.AddPostfix(patchInfo, instance.Id, postfix);
                        PatchFunctions.AddTranspiler(patchInfo, instance.Id, transpiler);
                        PatchFunctions.AddFinalizer(patchInfo, instance.Id, finalizer);
                        dynamicMethods.Add(PatchFunctions.UpdateWrapper(original, patchInfo, instance.Id));

                        HarmonySharedState.UpdatePatchInfo(original, patchInfo);

                        RunMethod <HarmonyCleanup>(original);
                    }
                }
                return(dynamicMethods);
            }
        }
예제 #7
0
        /// <summary>Unpatches patches of a given type and/or Harmony ID</summary>
        /// <param name="type">The patch type</param>
        /// <param name="harmonyID">Harmony ID or (*) for any</param>
        ///
        public void Unpatch(HarmonyPatchType type, string harmonyID)
        {
            lock (locker)
            {
                foreach (var original in originals)
                {
                    var patchInfo = HarmonySharedState.GetPatchInfo(original);
                    if (patchInfo == null)
                    {
                        patchInfo = new PatchInfo();
                    }

                    if (type == HarmonyPatchType.All || type == HarmonyPatchType.Prefix)
                    {
                        PatchFunctions.RemovePrefix(patchInfo, harmonyID);
                    }
                    if (type == HarmonyPatchType.All || type == HarmonyPatchType.Postfix)
                    {
                        PatchFunctions.RemovePostfix(patchInfo, harmonyID);
                    }
                    if (type == HarmonyPatchType.All || type == HarmonyPatchType.Transpiler)
                    {
                        PatchFunctions.RemoveTranspiler(patchInfo, harmonyID);
                    }
                    if (type == HarmonyPatchType.All || type == HarmonyPatchType.Finalizer)
                    {
                        PatchFunctions.RemoveFinalizer(patchInfo, harmonyID);
                    }
                    PatchFunctions.UpdateWrapper(original, patchInfo, instance.Id);

                    HarmonySharedState.UpdatePatchInfo(original, patchInfo);
                }
            }
        }
예제 #8
0
        void ProcessPatchJob(PatchJobs <MethodInfo> .Job job)
        {
            MethodInfo replacement = default;

            var       individualPrepareResult = RunMethod <HarmonyPrepare, bool>(true, false, null, job.original);
            Exception exception = null;

            if (individualPrepareResult)
            {
                lock (PatchProcessor.locker)
                {
                    try
                    {
                        var patchInfo = HarmonySharedState.GetPatchInfo(job.original);
                        if (patchInfo == null)
                        {
                            patchInfo = new PatchInfo();
                        }

                        foreach (var prefix in job.prefixes)
                        {
                            PatchFunctions.AddPrefix(patchInfo, instance.Id, prefix);
                        }
                        foreach (var postfix in job.postfixes)
                        {
                            PatchFunctions.AddPostfix(patchInfo, instance.Id, postfix);
                        }
                        foreach (var transpiler in job.transpilers)
                        {
                            PatchFunctions.AddTranspiler(patchInfo, instance.Id, transpiler);
                        }
                        foreach (var finalizer in job.finalizers)
                        {
                            PatchFunctions.AddFinalizer(patchInfo, instance.Id, finalizer);
                        }

                        replacement = PatchFunctions.UpdateWrapper(job.original, patchInfo);
                        HarmonySharedState.UpdatePatchInfo(job.original, patchInfo);
                    }
                    catch (Exception ex)
                    {
                        exception = ex;
                    }
                }
            }
            RunMethod <HarmonyCleanup>(ref exception, job.original, exception);
            if (exception != null)
            {
                ReportException(exception, job.original);
            }
            job.replacement = replacement;
        }
예제 #9
0
        /// <summary>Unpatches a specific patch</summary>
        /// <param name="patch">The method of the patch</param>
        /// <returns>A <see cref="PatchProcessor"/> for chaining calls</returns>
        ///
        public PatchProcessor Unpatch(MethodInfo patch)
        {
            lock (locker)
            {
                var patchInfo = original.ToPatchInfo();

                patchInfo.RemovePatch(patch);
                var replacement = PatchFunctions.UpdateWrapper(original, patchInfo);

                PatchManager.AddReplacementOriginal(original, replacement);
                return(this);
            }
        }
예제 #10
0
        /// <summary>Unpatches a specific patch</summary>
        /// <param name="patch">The method of the patch</param>
        /// <returns>A <see cref="PatchProcessor"/> for chaining calls</returns>
        ///
        public PatchProcessor Unpatch(MethodInfo patch)
        {
            lock (locker)
            {
                var patchInfo = HarmonySharedState.GetPatchInfo(original);
                if (patchInfo == null)
                {
                    patchInfo = new PatchInfo();
                }

                PatchFunctions.RemovePatch(patchInfo, patch);
                _ = PatchFunctions.UpdateWrapper(original, patchInfo);

                HarmonySharedState.UpdatePatchInfo(original, patchInfo);
                return(this);
            }
        }
예제 #11
0
        /// <summary>Unpatches the given patch</summary>
        /// <param name="patch">The patch</param>
        ///
        public void Unpatch(MethodInfo patch)
        {
            lock (locker)
            {
                foreach (var original in originals)
                {
                    var patchInfo = HarmonySharedState.GetPatchInfo(original);
                    if (patchInfo == null)
                    {
                        patchInfo = new PatchInfo();
                    }

                    PatchFunctions.RemovePatch(patchInfo, patch);
                    PatchFunctions.UpdateWrapper(original, patchInfo, instance.Id);

                    HarmonySharedState.UpdatePatchInfo(original, patchInfo);
                }
            }
        }