예제 #1
0
        /// <summary>Creates new replacement method with the latest patches and detours the original method</summary>
        /// <param name="original">The original method</param>
        /// <param name="patchInfo">Information describing the patches</param>
        /// <returns>The newly created replacement method</returns>
        ///
        internal static MethodInfo UpdateWrapper(MethodBase original, PatchInfo patchInfo)
        {
            var debug = patchInfo.Debugging || Harmony.DEBUG;

            var sortedPrefixes    = GetSortedPatchMethods(original, patchInfo.prefixes, debug);
            var sortedPostfixes   = GetSortedPatchMethods(original, patchInfo.postfixes, debug);
            var sortedTranspilers = GetSortedPatchMethods(original, patchInfo.transpilers, debug);
            var sortedFinalizers  = GetSortedPatchMethods(original, patchInfo.finalizers, debug);

            var patcher     = new MethodPatcher(original, null, sortedPrefixes, sortedPostfixes, sortedTranspilers, sortedFinalizers, debug);
            var replacement = patcher.CreateReplacement(out var finalInstructions);

            if (replacement == null)
            {
                throw new MissingMethodException($"Cannot create replacement for {original.FullDescription()}");
            }

            try
            {
                Memory.DetourMethodAndPersist(original, replacement);
            }
            catch (Exception ex)
            {
                throw HarmonyException.Create(ex, finalInstructions);
            }
            return(replacement);
        }
예제 #2
0
        internal static MethodInfo ReversePatch(HarmonyMethod standin, MethodBase original, MethodInfo postTranspiler)
        {
            if (standin == null)
            {
                throw new ArgumentNullException(nameof(standin));
            }
            if (standin.method == null)
            {
                throw new ArgumentNullException($"{nameof(standin)}.{nameof(standin.method)}");
            }

            var debug = (standin.debug ?? false) || Harmony.DEBUG;

            var transpilers = new List <MethodInfo>();

            if (standin.reversePatchType == HarmonyReversePatchType.Snapshot)
            {
                var info = Harmony.GetPatchInfo(original);
                transpilers.AddRange(GetSortedPatchMethods(original, info.Transpilers.ToArray(), debug));
            }
            if (postTranspiler != null)
            {
                transpilers.Add(postTranspiler);
            }

            var empty       = new List <MethodInfo>();
            var patcher     = new MethodPatcher(standin.method, original, empty, empty, transpilers, empty, debug);
            var replacement = patcher.CreateReplacement(out var finalInstructions);

            if (replacement == null)
            {
                throw new MissingMethodException($"Cannot create replacement for {standin.method.FullDescription()}");
            }

            try
            {
                var errorString = Memory.DetourMethod(standin.method, replacement);
                if (errorString != null)
                {
                    throw new FormatException($"Method {standin.method.FullDescription()} cannot be patched. Reason: {errorString}");
                }
            }
            catch (Exception ex)
            {
                throw HarmonyException.Create(ex, finalInstructions);
            }

            PatchTools.RememberObject(standin.method, replacement);
            return(replacement);
        }
예제 #3
0
        /// <summary>Creates new replacement method with the latest patches and detours the original method</summary>
        /// <param name="original">The original method</param>
        /// <param name="patchInfo">Information describing the patches</param>
        /// <returns>The newly created replacement method</returns>
        ///
        internal static MethodInfo UpdateWrapper(MethodBase original, PatchInfo patchInfo)
        {
            var patcher = original.GetMethodPatcher();
            var dmd     = patcher.PrepareOriginal();

            if (dmd != null)
            {
                var ctx = new ILContext(dmd.Definition);
                HarmonyManipulator.Manipulate(original, patchInfo, ctx);
            }

            try
            {
                return(patcher.DetourTo(dmd?.Generate()) as MethodInfo);
            }
            catch (Exception ex)
            {
                throw HarmonyException.Create(ex, dmd?.Definition?.Body);
            }
        }