using System.Collections.Generic; using System.Reflection; using HarmonyLib; using NitroxModel.Core; using NitroxModel.Helper; namespace NitroxPatcher.Patches; /// /// Base class for declaring a patch using . /// Implement either if your patch is unloadable or if it isn't.
/// Either one or more of the following patch types are possible in one :
/// - Prefix patch, use
/// - Postfix patch, use
/// - Transpiler patch, use
/// - Finalizer patch, use
///

/// Documentation for patching can be found under https://harmony.pardeike.net/articles/patching.html and https://github.com/BepInEx/HarmonyX/wiki/Difference-between-Harmony-and-HarmonyX ///

public abstract class NitroxPatch : INitroxPatch { /// /// List of patches defined by the class that inherits. /// private readonly List activePatches = new(); public abstract void Patch(Harmony harmony); /// /// Removes the (previously applied) patches from the process. /// /// public void Restore(Harmony harmony) { foreach (MethodBase targetMethod in activePatches) { harmony.Unpatch(targetMethod, HarmonyPatchType.All, harmony.Id); } } protected void PatchFinalizer(Harmony harmony, MethodBase targetMethod, MethodInfo finalizerMethod) { PatchMultiple(harmony, targetMethod, null, null, null, finalizerMethod); } protected void PatchTranspiler(Harmony harmony, MethodBase targetMethod, MethodInfo transpilerMethod) { PatchMultiple(harmony, targetMethod, null, null, transpilerMethod); } protected void PatchPrefix(Harmony harmony, MethodBase targetMethod, MethodInfo prefixMethod) { PatchMultiple(harmony, targetMethod, prefixMethod); } protected void PatchPostfix(Harmony harmony, MethodBase targetMethod, MethodInfo postfixMethod) { PatchMultiple(harmony, targetMethod, null, postfixMethod); } protected void PatchMultiple( Harmony harmony, MethodBase targetMethod, MethodInfo prefix = null, MethodInfo postfix = null, MethodInfo transpiler = null, MethodInfo finalizer = null, MethodInfo manipulator = null) { static HarmonyMethod AsHarmonyMethod(MethodInfo methodInfo) => methodInfo != null ? new HarmonyMethod(methodInfo) : null; Validate.NotNull(targetMethod, "Target method cannot be null"); harmony.Patch(targetMethod, AsHarmonyMethod(prefix), AsHarmonyMethod(postfix), AsHarmonyMethod(transpiler), AsHarmonyMethod(finalizer), AsHarmonyMethod(manipulator)); activePatches.Add(targetMethod); // Store our patched methods } /// /// Resolves a type using . If the result is not null it will cache and return the same type on future calls. /// /// Type to get and cache from /// The requested type or null if not available. protected static T Resolve(bool prelifeTime = false) where T : class { return prelifeTime ? NitroxServiceLocator.Cache.ValuePreLifetime : NitroxServiceLocator.Cache.Value; } }