using System; using System.Diagnostics; using System.Reflection; using NLog; using Torch.Managers.PatchManager; namespace Global.Patches { public static class Patcher { private static readonly Logger Log = LogManager.GetCurrentClassLogger(); public static PatchContext ctx; public static void InitilizePatcherContext(PatchContext Context) { ctx = Context; } public static MethodInfo GetMethod(string TargetMethodName, BindingFlags Flags) { return MethodGet(typeof(T), TargetMethodName, Flags, null); } public static MethodInfo GetMethod( string TargetMethodName, BindingFlags Flags, Type[] Types) { return MethodGet(typeof(T), TargetMethodName, Flags, Types); } public static MethodInfo SuffixPatch( string TargetMethodName, BindingFlags Flags, string ReplaceMentMethodName) { return Patch(false, typeof(T), TargetMethodName, Flags, ReplaceMentMethodName, null); } public static MethodInfo SuffixPatch( string TargetMethodName, BindingFlags Flags, Type[] Types, string ReplaceMentMethodName) { return Patch(false, typeof(T), TargetMethodName, Flags, ReplaceMentMethodName, Types); } public static MethodInfo PrePatch( string TargetMethodName, BindingFlags Flags, string ReplaceMentMethodName) { return Patch(true, typeof(T), TargetMethodName, Flags, ReplaceMentMethodName, null); } public static MethodInfo PrePatch( string TargetMethodName, BindingFlags Flags, Type[] Types, string ReplaceMentMethodName) { return Patch(true, typeof(T), TargetMethodName, Flags, ReplaceMentMethodName, Types); } private static MethodInfo Patch( bool PreFix, Type TargetClass, string TargetMethodName, BindingFlags Flags, string ReplaceMentMethodName, Type[] Types) { try { var method1 = Types != null ? TargetClass.GetMethod(TargetMethodName, Flags, null, Types, null) : TargetClass.GetMethod(TargetMethodName, Flags); if (method1 == null) { Log.Error("Unable to find patch method " + TargetClass.Name + "." + TargetMethodName); return null; } var declaringType = new StackFrame(2, false).GetMethod().DeclaringType; if (declaringType == null) Log.Error("Unable to find calling class!"); var method2 = declaringType.GetMethod(ReplaceMentMethodName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (PreFix) ctx.GetPattern(method1).Prefixes.Add(method2); else ctx.GetPattern(method1).Suffixes.Add(method2); return method1; } catch (AmbiguousMatchException ex) { Log.Error(ex, "You need to specify the method types! More than one method named: " + TargetClass.Name + "." + TargetMethodName, Array.Empty()); } catch (ArgumentException ex) { Log.Error(ex, "Invalid Arguments for " + TargetMethodName + " exsisting in: " + TargetClass.Name, Array.Empty()); } catch (Exception ex) { Log.Error(ex, "Unkown Patch Error!", Array.Empty()); } return null; } private static MethodInfo MethodGet( Type TargetClass, string TargetMethodName, BindingFlags Flags, Type[] Types) { var methodInfo = Types != null ? TargetClass.GetMethod(TargetMethodName, Flags, null, Types, null) : TargetClass.GetMethod(TargetMethodName, Flags); if (!(methodInfo == null)) return methodInfo; Log.Error("Unable to find patch method " + TargetClass.Name + "." + TargetMethodName); return null; } } }