using HarmonyLib; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace astealz.SmartSpawnController.Utils { public abstract class GenericPatch where T : GenericPatch { private Harmony _harmony; private HarmonyMethod _prefix; private HarmonyMethod _postfix; private HarmonyMethod _transpiler; private HarmonyMethod _finalizer; public GenericPatch(string name = null, string prefix = null, string postfix = null, string transpiler = null, string finalizer = null) { _harmony = new Harmony(name ?? typeof(T).Name); _prefix = GetPatchMethod(prefix); _postfix = GetPatchMethod(postfix); _transpiler = GetPatchMethod(transpiler); _finalizer = GetPatchMethod(finalizer); if (_prefix == null && _postfix == null && _transpiler == null && _finalizer == null) { throw new Exception($"{_harmony.Id}: At least one of the patch methods must be specified"); } } /// /// Get original method /// /// Method protected abstract MethodBase GetTargetMethod(); /// /// Get MethodInfo from string /// /// Method name /// Method private HarmonyMethod GetPatchMethod(string methodName) { if (string.IsNullOrWhiteSpace(methodName)) { return null; } return new HarmonyMethod(typeof(T).GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)); } /// /// Apply patch to target /// public void Apply() { var targetMethod = GetTargetMethod(); if (targetMethod == null) { throw new InvalidOperationException($"{_harmony.Id}: TargetMethod is null"); } try { _harmony.Patch(targetMethod, _prefix, _postfix, _transpiler, _finalizer); } catch (Exception ex) { throw new Exception($"{_harmony.Id}:", ex); } } /// /// Remove applied patch from target /// public void Remove() { var targetMethod = GetTargetMethod(); if (targetMethod == null) { throw new InvalidOperationException($"{_harmony.Id}: TargetMethod is null"); } try { _harmony.Unpatch(targetMethod, HarmonyPatchType.All, _harmony.Id); } catch (Exception ex) { throw new Exception($"{_harmony.Id}:", ex); } } } }