1using MonoMod.RuntimeDetour;
2using MonoMod.RuntimeDetour.HookGen;
5using System.Collections.Generic;
6using System.Diagnostics;
8using System.Reflection;
9using System.Reflection.Emit;
10using Terraria.ModLoader.Core;
11using Terraria.ModLoader.Default;
17 private static Dictionary<Type, string>
defaultAliases =
new Dictionary<Type, string> {
18 { typeof(
object),
"object" },
19 { typeof(
bool),
"bool" },
20 { typeof(
float),
"float" },
21 { typeof(
double),
"double" },
22 { typeof(decimal),
"decimal" },
23 { typeof(
byte),
"byte" },
24 { typeof(sbyte),
"sbyte" },
25 { typeof(
short),
"short" },
26 { typeof(ushort),
"ushort" },
27 { typeof(
int),
"int" },
28 { typeof(uint),
"uint" },
29 { typeof(
long),
"long" },
30 { typeof(ulong),
"ulong" },
31 { typeof(
char),
"char" },
32 { typeof(
string),
"string" }
35 private static DetourModManager
manager =
new DetourModManager();
39 internal static void Initialize() {
43 HookEndpointManager.OnAdd += (m, d) => {
44 Logging.tML.Debug($
"Hook On.{StringRep(m)} added by {GetOwnerName(d)}");
47 HookEndpointManager.OnRemove += (m, d) => {
48 Logging.tML.Debug($
"Hook On.{StringRep(m)} removed by {GetOwnerName(d)}");
51 HookEndpointManager.OnModify += (m, d) => {
52 Logging.tML.Debug($
"Hook IL.{StringRep(m)} modified by {GetOwnerName(d)}");
55 HookEndpointManager.OnUnmodify += (m, d) => {
56 Logging.tML.Debug($
"Hook IL.{StringRep(m)} unmodified by {GetOwnerName(d)}");
60 manager.OnHook += (
asm, from, to, target) => {
62 Logging.tML.Debug($
"Hook {StringRep(from)} -> {StringRep(to)} by {asm.GetName().Name}");
65 manager.OnILHook += (
asm, from, manipulator) => {
67 Logging.tML.Debug($
"ILHook {StringRep(from)} by {asm.GetName().Name}");
70 manager.OnDetour += (
asm, from, to) => {
72 Logging.tML.Debug($
"Detour {StringRep(from)} -> {StringRep(to)} by {asm.GetName().Name}");
75 manager.OnNativeDetour += (
asm, method, from, to) => {
77 Logging.tML.Debug($
"NativeDetour {StringRep(method)} [{from} -> {to}] by {asm.GetName().Name}");
87 throw new UnauthorizedAccessException(
88 $
"Native detouring permissions not granted to {asm.GetName().Name}. \n" +
89 $
"Mods should use HookEndpointManager for compatibility. \n" +
90 $
"If Detour or NativeDetour are required, call MonoModHooks.RequestNativeAccess()");
94 var stack =
new StackTrace();
95 var
asm = stack.GetFrame(1).GetMethod().DeclaringType.Assembly;
97 Logging.tML.Warn($
"Granted native detouring access to {asm.GetName().Name}");
101 return d.Method.DeclaringType.Assembly.GetName().Name;
105 var paramString =
string.Join(
", ", m.GetParameters().Select(p => {
106 var t = p.ParameterType;
110 s = p.IsOut ?
"out " :
"ref ";
111 t = t.GetElementType();
114 return s + (
defaultAliases.TryGetValue(t, out
string n) ? n : t.Name);
117 var owner = m.DeclaringType?.FullName ??
118 (m is DynamicMethod ?
"dynamic" :
"unknown");
119 return $
"{owner}::{m.Name}({paramString})";
122 internal static void RemoveAll(Mod mod) {
123 if (mod is ModLoaderMod)
126 int hooks = 0, detours = 0, ndetours = 0;
127 bool OnHookUndo(
object obj) {
131 bool OnDetourUndo(
object obj) {
135 bool OnNativeDetourUndo(
object obj) {
140 Hook.OnUndo += OnHookUndo;
141 Detour.OnUndo += OnDetourUndo;
142 NativeDetour.OnUndo += OnNativeDetourUndo;
144 foreach (var
asm in AssemblyManager.GetModAssemblies(mod.Name))
147 Hook.OnUndo -= OnHookUndo;
148 Detour.OnUndo -= OnDetourUndo;
149 NativeDetour.OnUndo -= OnNativeDetourUndo;
151 if (hooks > 0 || detours > 0 || ndetours > 0)
152 Logging.tML.Debug($
"Unloaded {hooks} hooks, {detours} detours and {ndetours} native detours from {mod.Name}");
static string GetOwnerName(Delegate d)
static Dictionary< Type, string > defaultAliases
static string StringRep(MethodBase m)
static bool isInitialized
static void NativeAccessCheck(Assembly asm)
static void RequestNativeAccess()
static HashSet< Assembly > NativeDetouringGranted
static DetourModManager manager