mirror of
https://github.com/D1GQ/BetterAmongUs.git
synced 2026-10-19 15:51:52 +00:00
Move to hooking for mono extension
This commit is contained in:
1 parent
61e355f103
commit
72a7864622
4 files changed
+45
-47
No files matched your search
+3
-3
@@ -16,7 +16,7 @@ using BetterAmongUs.Modules.Support;
|
|||||||
using BetterAmongUs.Network;
|
using BetterAmongUs.Network;
|
||||||
using BetterAmongUs.Patches.Client;
|
using BetterAmongUs.Patches.Client;
|
||||||
using BetterAmongUs.Patches.Gameplay.UI.Settings;
|
using BetterAmongUs.Patches.Gameplay.UI.Settings;
|
||||||
using BetterAmongUs.Patches.Unity;
|
using BetterAmongUs.Patches.Hooks;
|
||||||
using BetterAmongUs.Utilities;
|
using BetterAmongUs.Utilities;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@@ -159,7 +159,7 @@ internal class BAUPlugin : BasePlugin
|
|||||||
AudioOverrideManager.Initialize();
|
AudioOverrideManager.Initialize();
|
||||||
Translator.Initialize();
|
Translator.Initialize();
|
||||||
Harmony.PatchAll();
|
Harmony.PatchAll();
|
||||||
MonoExtensionPatch.Patch(Harmony);
|
MonoExtensionHook.Install();
|
||||||
GameSettingsPatch.SetupSettings(true);
|
GameSettingsPatch.SetupSettings(true);
|
||||||
BAUModdedSupportEvents.OnBAUOptionsLoadedEvent.InvokeAll([.. OptionItem.AllOptions.Cast<object>()]);
|
BAUModdedSupportEvents.OnBAUOptionsLoadedEvent.InvokeAll([.. OptionItem.AllOptions.Cast<object>()]);
|
||||||
AutoRegisterAttribute.Initialize();
|
AutoRegisterAttribute.Initialize();
|
||||||
@@ -186,7 +186,7 @@ internal class BAUPlugin : BasePlugin
|
|||||||
BetterNotificationManager.Detach();
|
BetterNotificationManager.Detach();
|
||||||
ClientPatch.Unpatch();
|
ClientPatch.Unpatch();
|
||||||
Harmony.UnpatchAll();
|
Harmony.UnpatchAll();
|
||||||
MonoExtensionPatch.Unpatch(Harmony);
|
MonoExtensionHook.Uninstall();
|
||||||
ModManager.Instance.ModStamp.gameObject.SetActive(false);
|
ModManager.Instance.ModStamp.gameObject.SetActive(false);
|
||||||
SceneChanger.ChangeScene("MainMenu");
|
SceneChanger.ChangeScene("MainMenu");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<LangVersion>preview</LangVersion>
|
<LangVersion>preview</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -1,89 +1,76 @@
|
|||||||
using BetterAmongUs.Interfaces;
|
using BetterAmongUs.Interfaces;
|
||||||
using BetterAmongUs.Modules;
|
using BetterAmongUs.Modules;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
|
using MonoMod.RuntimeDetour;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace BetterAmongUs.Patches.Unity;
|
namespace BetterAmongUs.Patches.Hooks;
|
||||||
|
|
||||||
[HarmonyPatch]
|
internal static class MonoExtensionHook
|
||||||
internal static class MonoExtensionPatch
|
|
||||||
{
|
{
|
||||||
private static bool _patched = false;
|
private static bool _patched = false;
|
||||||
private static readonly HashSet<Type> PatchedTypes = [];
|
private static readonly HashSet<Type> PatchedTypes = [];
|
||||||
|
private static readonly List<IDetour> _detours = [];
|
||||||
|
|
||||||
internal static void Patch(Harmony harmony)
|
internal static void Install()
|
||||||
{
|
{
|
||||||
if (_patched) return;
|
if (_patched) return;
|
||||||
_patched = true;
|
_patched = true;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Find all types that implement IMonoExtension
|
|
||||||
var extensionTypes = FindAllExtensionTypes();
|
var extensionTypes = FindAllExtensionTypes();
|
||||||
|
|
||||||
foreach (var extType in extensionTypes)
|
foreach (var extType in extensionTypes)
|
||||||
{
|
{
|
||||||
// Get the target MonoBehaviour type from IAutoMonoExtension<T>
|
|
||||||
var targetType = GetTargetMonoBehaviourType(extType);
|
var targetType = GetTargetMonoBehaviourType(extType);
|
||||||
if (targetType == null) continue;
|
if (targetType == null) continue;
|
||||||
|
|
||||||
// Only patch each target type once
|
|
||||||
if (!PatchedTypes.Add(targetType)) continue;
|
if (!PatchedTypes.Add(targetType)) continue;
|
||||||
|
|
||||||
// Patch the constructor of the target type
|
// Hook the IntPtr constructor
|
||||||
var constructor = AccessTools.Constructor(targetType, [typeof(IntPtr)]);
|
var constructor = AccessTools.Constructor(targetType, [typeof(IntPtr)]);
|
||||||
if (constructor != null)
|
if (constructor != null)
|
||||||
{
|
{
|
||||||
harmony.Patch(constructor,
|
var hook = new MonoMod.RuntimeDetour.Hook(
|
||||||
postfix: new HarmonyMethod(typeof(MonoExtensionPatch),
|
constructor,
|
||||||
nameof(MonoBehaviour_Constructor_Postfix)));
|
new Action<Action<MonoBehaviour, IntPtr>, 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));
|
var destroyMethod = AccessTools.Method(extType, nameof(IMonoExtension.OnDestroy));
|
||||||
if (destroyMethod != null)
|
if (destroyMethod != null)
|
||||||
{
|
{
|
||||||
harmony.Patch(destroyMethod,
|
var hook = new MonoMod.RuntimeDetour.Hook(
|
||||||
postfix: new HarmonyMethod(typeof(MonoExtensionPatch),
|
destroyMethod,
|
||||||
nameof(IMonoExtension_OnDestroy_Postfix)));
|
new Action<Action<IMonoExtension>, IMonoExtension>(IMonoExtension_OnDestroy_Hook)
|
||||||
|
);
|
||||||
|
_detours.Add(hook);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_patched = false;
|
_patched = false;
|
||||||
Logger_.Error($"Failed to patch MonoExtension methods: {ex.Message}");
|
Logger_.Error($"Failed to hook MonoExtension methods: {ex.Message}");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void Unpatch(Harmony harmony)
|
internal static void Uninstall()
|
||||||
{
|
{
|
||||||
if (!_patched) return;
|
if (!_patched) return;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var extensionTypes = FindAllExtensionTypes();
|
foreach (var detour in _detours)
|
||||||
|
|
||||||
foreach (var extType in extensionTypes)
|
|
||||||
{
|
{
|
||||||
var targetType = GetTargetMonoBehaviourType(extType);
|
detour.Dispose();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
_detours.Clear();
|
||||||
|
_patched = false;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -123,21 +110,31 @@ internal static class MonoExtensionPatch
|
|||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void MonoBehaviour_Constructor_Postfix(MonoBehaviour __instance)
|
private static void MonoBehaviour_Constructor_Hook(Action<MonoBehaviour, IntPtr> orig, MonoBehaviour instance, IntPtr ptr)
|
||||||
{
|
{
|
||||||
|
orig(instance, ptr);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (__instance == null) return;
|
IMonoExtension.TryAddAutoExtension(instance);
|
||||||
IMonoExtension.TryAddAutoExtension(__instance);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
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<IMonoExtension> orig, IMonoExtension instance)
|
||||||
{
|
{
|
||||||
IMonoExtension.TryRemoveExtension(__instance);
|
orig(instance);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IMonoExtension.TryRemoveExtension(instance);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger_.Error($"Error in OnDestroy hook: {ex.Message}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
using BetterAmongUs.Modules.Support;
|
using BetterAmongUs.Modules;
|
||||||
|
using BetterAmongUs.Modules.Support;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Networking;
|
using UnityEngine.Networking;
|
||||||
using BetterAmongUs.Modules;
|
|
||||||
|
|
||||||
namespace BetterAmongUs.Patches.Unity;
|
namespace BetterAmongUs.Patches.Unity;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user