From 72a7864622e5381b96f3582177bfd9a9108481ae Mon Sep 17 00:00:00 2001 From: D1GQ Date: Sat, 11 Jul 2026 04:56:39 -0500 Subject: [PATCH] Move to hooking for mono extension --- src/BAUPlugin.cs | 6 +- src/BetterAmongUs.csproj | 1 + .../MonoExtensionHook.cs} | 81 +++++++++---------- src/Patches/Unity/UnityWebRequestPatch.cs | 4 +- 4 files changed, 45 insertions(+), 47 deletions(-) rename src/Patches/{Unity/MonoExtensionPatch.cs => Hooks/MonoExtensionHook.cs} (50%) diff --git a/src/BAUPlugin.cs b/src/BAUPlugin.cs index b2ee6e1..7146cd1 100644 --- a/src/BAUPlugin.cs +++ b/src/BAUPlugin.cs @@ -16,7 +16,7 @@ using BetterAmongUs.Modules.Support; using BetterAmongUs.Network; using BetterAmongUs.Patches.Client; using BetterAmongUs.Patches.Gameplay.UI.Settings; -using BetterAmongUs.Patches.Unity; +using BetterAmongUs.Patches.Hooks; using BetterAmongUs.Utilities; using HarmonyLib; using UnityEngine; @@ -159,7 +159,7 @@ internal class BAUPlugin : BasePlugin AudioOverrideManager.Initialize(); Translator.Initialize(); Harmony.PatchAll(); - MonoExtensionPatch.Patch(Harmony); + MonoExtensionHook.Install(); GameSettingsPatch.SetupSettings(true); BAUModdedSupportEvents.OnBAUOptionsLoadedEvent.InvokeAll([.. OptionItem.AllOptions.Cast()]); AutoRegisterAttribute.Initialize(); @@ -186,7 +186,7 @@ internal class BAUPlugin : BasePlugin BetterNotificationManager.Detach(); ClientPatch.Unpatch(); Harmony.UnpatchAll(); - MonoExtensionPatch.Unpatch(Harmony); + MonoExtensionHook.Uninstall(); ModManager.Instance.ModStamp.gameObject.SetActive(false); SceneChanger.ChangeScene("MainMenu"); } diff --git a/src/BetterAmongUs.csproj b/src/BetterAmongUs.csproj index c6e7042..87b4959 100644 --- a/src/BetterAmongUs.csproj +++ b/src/BetterAmongUs.csproj @@ -3,6 +3,7 @@ net6.0 enable enable + true Library preview diff --git a/src/Patches/Unity/MonoExtensionPatch.cs b/src/Patches/Hooks/MonoExtensionHook.cs similarity index 50% rename from src/Patches/Unity/MonoExtensionPatch.cs rename to src/Patches/Hooks/MonoExtensionHook.cs index 1b5f57a..c0837c0 100644 --- a/src/Patches/Unity/MonoExtensionPatch.cs +++ b/src/Patches/Hooks/MonoExtensionHook.cs @@ -1,89 +1,76 @@ using BetterAmongUs.Interfaces; using BetterAmongUs.Modules; using HarmonyLib; +using MonoMod.RuntimeDetour; using UnityEngine; -namespace BetterAmongUs.Patches.Unity; +namespace BetterAmongUs.Patches.Hooks; -[HarmonyPatch] -internal static class MonoExtensionPatch +internal static class MonoExtensionHook { private static bool _patched = false; private static readonly HashSet PatchedTypes = []; + private static readonly List _detours = []; - internal static void Patch(Harmony harmony) + internal static void Install() { if (_patched) return; _patched = true; try { - // Find all types that implement IMonoExtension var extensionTypes = FindAllExtensionTypes(); foreach (var extType in extensionTypes) { - // Get the target MonoBehaviour type from IAutoMonoExtension var targetType = GetTargetMonoBehaviourType(extType); if (targetType == null) continue; - // Only patch each target type once if (!PatchedTypes.Add(targetType)) continue; - // Patch the constructor of the target type + // Hook the IntPtr constructor var constructor = AccessTools.Constructor(targetType, [typeof(IntPtr)]); if (constructor != null) { - harmony.Patch(constructor, - postfix: new HarmonyMethod(typeof(MonoExtensionPatch), - nameof(MonoBehaviour_Constructor_Postfix))); + var hook = new MonoMod.RuntimeDetour.Hook( + constructor, + new Action, MonoBehaviour, IntPtr>(MonoBehaviour_Constructor_Hook) + ); + _detours.Add(hook); } - // Patch OnDestroy method if it exists on the extension type + // Hook OnDestroy var destroyMethod = AccessTools.Method(extType, nameof(IMonoExtension.OnDestroy)); if (destroyMethod != null) { - harmony.Patch(destroyMethod, - postfix: new HarmonyMethod(typeof(MonoExtensionPatch), - nameof(IMonoExtension_OnDestroy_Postfix))); + var hook = new MonoMod.RuntimeDetour.Hook( + destroyMethod, + new Action, IMonoExtension>(IMonoExtension_OnDestroy_Hook) + ); + _detours.Add(hook); } } } catch (Exception ex) { _patched = false; - Logger_.Error($"Failed to patch MonoExtension methods: {ex.Message}"); + Logger_.Error($"Failed to hook MonoExtension methods: {ex.Message}"); throw; } } - internal static void Unpatch(Harmony harmony) + internal static void Uninstall() { if (!_patched) return; try { - var extensionTypes = FindAllExtensionTypes(); - - foreach (var extType in extensionTypes) + foreach (var detour in _detours) { - var targetType = GetTargetMonoBehaviourType(extType); - if (targetType == null) continue; - - // Unpatch constructor - var constructor = AccessTools.Constructor(targetType, [typeof(IntPtr)]); - if (constructor != null) - { - harmony.Unpatch(constructor, HarmonyPatchType.Postfix, harmony.Id); - } - - // Unpatch OnDestroy - var destroyMethod = AccessTools.Method(extType, nameof(IMonoExtension.OnDestroy)); - if (destroyMethod != null) - { - harmony.Unpatch(destroyMethod, HarmonyPatchType.Postfix, harmony.Id); - } + detour.Dispose(); } + _detours.Clear(); + _patched = false; } catch (Exception ex) { @@ -123,21 +110,31 @@ internal static class MonoExtensionPatch return types; } - private static void MonoBehaviour_Constructor_Postfix(MonoBehaviour __instance) + private static void MonoBehaviour_Constructor_Hook(Action orig, MonoBehaviour instance, IntPtr ptr) { + orig(instance, ptr); + try { - if (__instance == null) return; - IMonoExtension.TryAddAutoExtension(__instance); + IMonoExtension.TryAddAutoExtension(instance); } catch (Exception ex) { - Logger_.Error($"Error in MonoExtension constructor patch: {ex.Message}"); + Logger_.Error($"Error in constructor hook: {ex.Message}"); } } - private static void IMonoExtension_OnDestroy_Postfix(IMonoExtension __instance) + private static void IMonoExtension_OnDestroy_Hook(Action orig, IMonoExtension instance) { - IMonoExtension.TryRemoveExtension(__instance); + orig(instance); + + try + { + IMonoExtension.TryRemoveExtension(instance); + } + catch (Exception ex) + { + Logger_.Error($"Error in OnDestroy hook: {ex.Message}"); + } } } \ No newline at end of file diff --git a/src/Patches/Unity/UnityWebRequestPatch.cs b/src/Patches/Unity/UnityWebRequestPatch.cs index 20686ec..d45fc2d 100644 --- a/src/Patches/Unity/UnityWebRequestPatch.cs +++ b/src/Patches/Unity/UnityWebRequestPatch.cs @@ -1,9 +1,9 @@ -using BetterAmongUs.Modules.Support; +using BetterAmongUs.Modules; +using BetterAmongUs.Modules.Support; using HarmonyLib; using System.Text; using UnityEngine; using UnityEngine.Networking; -using BetterAmongUs.Modules; namespace BetterAmongUs.Patches.Unity;