public void Override(Type owner, string targetMethod, Type overrideParent, string overrideMethodName, Func <IEnumerable <CodeInstruction>, IEnumerable <CodeInstruction> > transpiler) { if (overrideMethodName.IsNullOrEmpty()) { throw new ArgumentException("overrideMethodName cannot be null or empty"); } if (overrideParent == null) { throw new ArgumentException("overrideParent cannot be null"); } MethodInfo overrideMethod = null; if (overrideParent.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).Any(x => x.Name == overrideMethodName)) { overrideMethod = overrideParent.GetMethod(overrideMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); } if (overrideMethod == null) { throw new MethodNotExistsException($"Unable to access {overrideParent.FullName}.{overrideMethodName}"); } MethodInfo original; if ((original = owner.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static) .FirstOrDefault(x => overrideMethod != null && SameParameters(x.GetParameters(), overrideMethod.GetParameters()))) == default) { throw new MethodNotExistsException($"{targetMethod} does not exist in {owner.FullName}"); } if (!SameParameters(original.GetParameters(), overrideMethod.GetParameters())) { throw new InvalidParametersException($"{overrideParent.FullName}.{overrideMethodName} must have the exact same parameters as the original function"); } if (!overrideMethod.IsStatic) { throw new InvalidParametersException($"{overrideParent.FullName}.{overrideMethod.Name} is not a static function"); } WriteLogger($"Got a request from {overrideParent.FullName}.{overrideMethod.Name} for {owner.FullName}.{targetMethod}"); var eventItem = new Event(original, overrideParent, overrideMethod, null, null); eventItem.PatchedMethod = _instance.Patch(eventItem.Original, eventItem.HPrefix, null, new HarmonyMethod(transpiler.Method)); Events.Add(eventItem); WriteLogger($"Adding {overrideParent.FullName}.{overrideMethod.Name} to patch cycle {owner.FullName}.{targetMethod}"); WriteLogger($"{eventItem.PatchedMethod.Name} is linked to {overrideParent.FullName}.{overrideMethod.Name}"); }
public void ConstructorOverride(Type owner, Type overrideParent, string overrideMethodName, Func <IEnumerable <CodeInstruction>, IEnumerable <CodeInstruction> > transpiler) { if (overrideMethodName.IsNullOrEmpty()) { throw new ArgumentException("overrideMethodName cannot be null or empty"); } if (overrideParent == null) { throw new ArgumentException("overrideParent cannot be null"); } MethodInfo overrideMethod = null; if (overrideParent.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).Any(x => x.Name == overrideMethodName)) { overrideMethod = overrideParent.GetMethod(overrideMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); } if (overrideMethod == null) { throw new MethodNotExistsException($"Unable to access {overrideParent.FullName}.{overrideMethodName}"); } var original = AccessTools.Constructor(owner); var eventItem = new Event(original, overrideParent, overrideMethod); eventItem.PatchedMethod = _instance.Patch(eventItem.OriginalConstructor, eventItem.HPrefix, new HarmonyMethod(transpiler.Method)); Events.Add(eventItem); WriteLogger($"Adding {overrideParent.FullName}.{overrideMethod.Name} to patch cycle {owner.FullName}.Constructor"); }
public void Add(Type owner, string targetMethod, Type runBeforeParent = null, string runBeforeMethodName = null, Type runAfterParent = null, string runAfterMethodName = null) { if (runBeforeMethodName.IsNullOrEmpty() && runAfterMethodName.IsNullOrEmpty()) { throw new ArgumentException("runBeforeMethod and runAfterMethod arguments cannot be both null"); } if (!runBeforeMethodName.IsNullOrEmpty() && runBeforeParent == null || !runAfterMethodName.IsNullOrEmpty() && runAfterParent == null) { throw new ArgumentException("runBeforeMethod and runAfterMethod's parents cannot be null if they are not null"); } MethodInfo runBefore = null; MethodInfo runAfter = null; if (!runBeforeMethodName.IsNullOrEmpty() && runBeforeParent != null) { if (runBeforeParent.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).Any(x => x.Name == runBeforeMethodName)) { runBefore = runBeforeParent.GetMethod(runBeforeMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); } if (runBefore == null) { throw new MethodNotExistsException($"Unable to access {runBeforeParent.FullName}.{runBeforeMethodName}"); } } if (!runAfterMethodName.IsNullOrEmpty() && runAfterParent != null) { if (runAfterParent.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).Any(x => x.Name == runAfterMethodName)) { runAfter = runAfterParent.GetMethod(runAfterMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); } if (runAfter == null) { throw new MethodNotExistsException($"Unable to access {runAfterParent.FullName}.{runAfterMethodName}"); } } MethodInfo original; if ((original = owner.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static) .FirstOrDefault(x => runBefore != null && SameParameters(x.GetParameters(), runBefore.GetParameters()) || runAfter != null && SameParameters(x.GetParameters(), runAfter.GetParameters()))) == default) { throw new MethodNotExistsException($"{targetMethod} does not exist in {owner.FullName}"); } if (runBefore != null) { if (!SameParameters(original.GetParameters(), runBefore.GetParameters())) { throw new InvalidParametersException($"{runBeforeParent.FullName}.{runBeforeMethodName} must have the exact same parameters as the original function"); } if (!runBefore.IsStatic) { throw new InvalidParametersException($"{runBeforeParent.FullName}.{runBefore.Name} is not a static function"); } } if (runAfter != null) { if (!SameParameters(original.GetParameters(), runAfter.GetParameters())) { throw new InvalidParametersException($"{runAfterParent.FullName}.{runAfterMethodName} must have the exact same parameters as the original function"); } if (!runAfter.IsStatic) { throw new InvalidParametersException($"{runAfterParent.FullName}.{runAfter.Name} is not a static function"); } } if (runBefore != null) { WriteLogger($"Got a request from {runBeforeParent.FullName}.{runBefore.Name} for {owner.FullName}.{targetMethod} prefix"); } if (runAfter != null) { WriteLogger($"Got a request from {runAfterParent.FullName}.{runAfter.Name} for {owner.FullName}.{targetMethod} postfix"); } var eventItem = new Event(original, runBeforeParent, runBefore, runAfterParent, runAfter); eventItem.PatchedMethod = _instance.Patch(eventItem.Original, eventItem.HPrefix, eventItem.HPostfix); Events.Add(eventItem); if (runBefore != null) { WriteLogger($"Adding {runBeforeParent.FullName}.{runBefore.Name} to prefix patch cycle {owner.FullName}.{targetMethod}"); WriteLogger($"{eventItem.PatchedMethod.Name} is linked to {runBeforeParent.FullName}.{runBefore.Name}"); } if (runAfter != null) { WriteLogger($"Adding {runAfterParent.FullName}.{runAfter.Name} to postfix patch cycle {owner.FullName}.{targetMethod}"); WriteLogger($"{eventItem.PatchedMethod.Name} is linked to {runAfterParent.FullName}.{runAfter.Name}"); } }