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;
}
}