void ReversePatch(ref MethodBase lastOriginal) { for (var i = 0; i < patchMethods.Count; i++) { var patchMethod = patchMethods[i]; if (patchMethod.type == HarmonyPatchType.ReversePatch) { lastOriginal = patchMethod.info.GetOriginalMethod(); var reversePatcher = instance.CreateReversePatcher(lastOriginal, patchMethod.info); lock (PatchProcessor.locker) _ = reversePatcher.Patch(); } } }
private void PrepareType() { var mainPrepareResult = RunMethod <HarmonyPrepare, bool>(true); if (mainPrepareResult == false) { return; } var originalMethodType = containerAttributes.methodType; // MethodType default is Normal if (containerAttributes.methodType == null) { containerAttributes.methodType = MethodType.Normal; } var reversePatchAttr = typeof(HarmonyReversePatch).FullName; var reversePatchMethods = container.GetMethods(AccessTools.all).Where(m => m.GetCustomAttributes(true).Any(a => a.GetType().FullName == reversePatchAttr)).ToList(); foreach (var reversePatchMethod in reversePatchMethods) { var attr = containerAttributes.Merge(new HarmonyMethod(reversePatchMethod)); var originalMethod = GetOriginalMethod(attr); var reversePatcher = instance.CreateReversePatcher(originalMethod, reversePatchMethod); reversePatcher.Patch(); } var customOriginals = RunMethod <HarmonyTargetMethods, IEnumerable <MethodBase> >(null); if (customOriginals != null) { originals.Clear(); originals.AddRange(customOriginals); } else { var isPatchAll = container.GetCustomAttributes(true).Any(a => a.GetType().FullName == typeof(HarmonyPatchAll).FullName); if (isPatchAll) { var type = containerAttributes.declaringType; originals.AddRange(AccessTools.GetDeclaredConstructors(type).Cast <MethodBase>()); originals.AddRange(AccessTools.GetDeclaredMethods(type).Cast <MethodBase>()); var props = AccessTools.GetDeclaredProperties(type); originals.AddRange(props.Select(prop => prop.GetGetMethod(true)).Where(method => method != null) .Cast <MethodBase>()); originals.AddRange(props.Select(prop => prop.GetSetMethod(true)).Where(method => method != null) .Cast <MethodBase>()); } else { var original = RunMethod <HarmonyTargetMethod, MethodBase>(null) ?? GetOriginalMethod(containerAttributes); if (original == null) { var info = "("; info += $"declaringType={containerAttributes.declaringType}, "; info += $"methodName ={containerAttributes.methodName}, "; info += $"methodType={originalMethodType}, "; info += $"argumentTypes={containerAttributes.argumentTypes.Description()}"; info += ")"; throw new ArgumentException( $"No target method specified for class {container.FullName} {info}"); } originals.Add(original); } } GetPatches(container, out var prefixMethod, out var postfixMethod, out var transpilerMethod, out var finalizerMethod); if (prefix != null) { prefix.method = prefixMethod; } if (postfix != null) { postfix.method = postfixMethod; } if (transpiler != null) { transpiler.method = transpilerMethod; } if (finalizer != null) { finalizer.method = finalizerMethod; } if (prefixMethod != null) { if (prefixMethod.IsStatic == false) { throw new ArgumentException($"Patch method {prefixMethod.GetID()} must be static"); } var prefixAttributes = HarmonyMethodExtensions.GetFromMethod(prefixMethod); containerAttributes.Merge(HarmonyMethod.Merge(prefixAttributes)).CopyTo(prefix); } if (postfixMethod != null) { if (postfixMethod.IsStatic == false) { throw new ArgumentException($"Patch method {postfixMethod.GetID()} must be static"); } var postfixAttributes = HarmonyMethodExtensions.GetFromMethod(postfixMethod); containerAttributes.Merge(HarmonyMethod.Merge(postfixAttributes)).CopyTo(postfix); } if (transpilerMethod != null) { if (transpilerMethod.IsStatic == false) { throw new ArgumentException($"Patch method {transpilerMethod.GetID()} must be static"); } var transpilerAttributes = HarmonyMethodExtensions.GetFromMethod(transpilerMethod); containerAttributes.Merge(HarmonyMethod.Merge(transpilerAttributes)).CopyTo(transpiler); } if (finalizerMethod != null) { if (finalizerMethod.IsStatic == false) { throw new ArgumentException($"Patch method {finalizerMethod.GetID()} must be static"); } var finalizerAttributes = HarmonyMethodExtensions.GetFromMethod(finalizerMethod); containerAttributes.Merge(HarmonyMethod.Merge(finalizerAttributes)).CopyTo(finalizer); } }