Skip to content

Instantly share code, notes, and snippets.

@factubsio
Created January 10, 2026 19:43
Show Gist options
  • Select an option

  • Save factubsio/9de42ae19308493c72359df5d09fdd7c to your computer and use it in GitHub Desktop.

Select an option

Save factubsio/9de42ae19308493c72359df5d09fdd7c to your computer and use it in GitHub Desktop.
public class BubblePatch(MethodBase target, HarmonyMethod Patch, HarmonyPatchType patchType)
{
private BubblePatch(MethodBase target, Type patcher, string name, HarmonyPatchType patchType) : this(target, new HarmonyMethod(patcher, name), patchType) { }
private BubblePatch(MethodBase target, Action patchDelegate, HarmonyPatchType patchType) : this(target, new HarmonyMethod(patchDelegate), patchType) { }
public bool IsPatched = false;
public static BubblePatch FirstConstructor(Type target, Type patcher, HarmonyPatchType patchType)
{
return new BubblePatch(target.GetConstructors().First(), patcher, "_ctor", patchType);
}
public static BubblePatch Setter(Type target, Type patcher, string propertyName, HarmonyPatchType patchType)
{
return new BubblePatch(target.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).SetMethod, patcher, $"set_{propertyName}", patchType);
}
public static BubblePatch Getter(Type target, Type patcher, string propertyName, HarmonyPatchType patchType)
{
return new BubblePatch(target.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetMethod, patcher, $"get_{propertyName}", patchType);
}
public static BubblePatch Method(Type target, Type patcher, string name, HarmonyPatchType patchType)
{
return new BubblePatch(target.GetMethod(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance), patcher, name, patchType);
}
public static BubblePatch Simple(Type target, string name, Action action, HarmonyPatchType patchType)
{
return new BubblePatch(target.GetMethod(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance), action, patchType);
}
public void Revert(bool modifySet = true)
{
if (!IsPatched)
return;
if (modifySet)
_Patches.Remove(this);
Main.HarmonyInstance.Unpatch(target, Patch.method);
IsPatched = false;
}
public void Apply()
{
if (IsPatched)
throw new Exception("Trying to apply a patch that is already applied");
switch (patchType)
{
case HarmonyPatchType.Prefix:
Main.HarmonyInstance.Patch(target, prefix: Patch);
break;
case HarmonyPatchType.Postfix:
Main.HarmonyInstance.Patch(target, postfix: Patch);
break;
case HarmonyPatchType.Finalizer:
Main.HarmonyInstance.Patch(target, finalizer: Patch);
break;
case HarmonyPatchType.Transpiler:
Main.HarmonyInstance.Patch(target, transpiler: Patch);
break;
}
_Patches.Add(this);
IsPatched = true;
}
private static readonly HashSet<BubblePatch> _Patches = [];
internal static void RevertAll()
{
foreach (var patch in _Patches)
{
patch.Revert(false);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment