Skip to content

Commit 82053a5

Browse files
fixed
1 parent 9e193d1 commit 82053a5

2 files changed

Lines changed: 108 additions & 17 deletions

File tree

services/DebugService.cs

Lines changed: 93 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,121 @@
1+
using System.Diagnostics;
12
using System.Reflection;
23
using HarmonyLib;
34
using NeoModLoader.constants;
45

56
namespace NeoModLoader.services;
67

8+
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
9+
public class DebugAttribute : Attribute{}
710
public static class DebugService
811
{
9-
static void Debugger(MethodBase __originalMethod)
12+
static bool IsDebuggable(MethodBase method)
1013
{
11-
LogService.LogInfo(__originalMethod.ToString());
14+
if (method.IsAbstract || method.ContainsGenericParameters || method.IsSpecialName || method.Name.Contains("<"))
15+
{
16+
return false;
17+
}
18+
return true;
1219
}
13-
static readonly Harmony Patcher = new Harmony(Others.harmony_id);
14-
private static readonly HarmonyMethod Hook = new(AccessTools.Method(typeof(DebugService), nameof(Debugger)));
15-
public static void AttachDebugger(Assembly assembly)
20+
public abstract class Debugger
1621
{
17-
foreach (var Type in assembly.GetTypes())
22+
protected HarmonyMethod Prefix;
23+
protected HarmonyMethod Postfix;
24+
protected HarmonyMethod Finalizer;
25+
public void Attach(Assembly assembly, Func<MethodBase, bool> predicate = null)
1826
{
27+
foreach (var Type in assembly.GetTypes())
28+
{
29+
Attach(Type, predicate);
30+
}
31+
}
32+
public void Attach(Type Type, Func<MethodBase, bool> predicate = null)
33+
{
34+
predicate ??= Default;
1935
foreach (var method in Type.GetMethods(
2036
BindingFlags.Public |
2137
BindingFlags.NonPublic |
2238
BindingFlags.Instance |
2339
BindingFlags.Static |
24-
BindingFlags.DeclaredOnly))
40+
BindingFlags.DeclaredOnly).Where(m => IsDebuggable(m) && predicate(m)))
2541
{
26-
Patcher.Patch(method, Hook);
42+
Attach(method);
2743
}
28-
}
29-
}
30-
public static void RemoveDebugger(Assembly assembly)
31-
{
32-
foreach (var Type in assembly.GetTypes())
33-
{
34-
foreach (var method in Type.GetMethods(
44+
foreach (var method in Type.GetConstructors(
3545
BindingFlags.Public |
3646
BindingFlags.NonPublic |
3747
BindingFlags.Instance |
3848
BindingFlags.Static |
39-
BindingFlags.DeclaredOnly))
49+
BindingFlags.DeclaredOnly).Where(m => IsDebuggable(m) && predicate(m)))
50+
{
51+
Attach(method);
52+
}
53+
}
54+
public void Attach(MethodBase method)
55+
{
56+
try
4057
{
41-
Patcher.Unpatch(method, HarmonyPatchType.Prefix);
58+
Patcher.Patch(method, Prefix, Postfix, null, Finalizer, null);
59+
}
60+
catch (Exception e)
61+
{
62+
LogService.LogError($"Failed to attach debugger to {method.FullDescription()} due to {e}");
4263
}
4364
}
4465
}
66+
public class LogDebugger : Debugger
67+
{
68+
static void prefix(MethodBase __originalMethod)
69+
{
70+
LogService.Log(__originalMethod.ToString());
71+
}
72+
public LogDebugger()
73+
{
74+
Prefix = new HarmonyMethod(AccessTools.Method(typeof(LogDebugger), nameof(prefix)));
75+
}
76+
}
77+
public class ProfilerDebugger : Debugger
78+
{
79+
static Stopwatch stopwatch = new();
80+
public static void prefix(out long __state)
81+
{
82+
__state = Stopwatch.GetTimestamp();
83+
}
84+
public static void postfix(
85+
MethodBase __originalMethod,
86+
long __state)
87+
{
88+
LogService.Log(
89+
$"{__originalMethod.Name} took {Stopwatch.GetTimestamp() - __state}");
90+
}
91+
public ProfilerDebugger()
92+
{
93+
Prefix = new HarmonyMethod(AccessTools.Method(typeof(ProfilerDebugger), nameof(prefix)));
94+
Postfix = new HarmonyMethod(AccessTools.Method(typeof(ProfilerDebugger), nameof(postfix)));
95+
}
96+
}
97+
public class ExceptionDebugger : Debugger
98+
{
99+
static void finalizer(Exception __exception, MethodBase __original)
100+
{
101+
if (__exception is not null)
102+
handler?.Invoke(__exception, __original);
103+
}
104+
public ExceptionDebugger()
105+
{
106+
Finalizer = new HarmonyMethod(AccessTools.Method(typeof(ExceptionDebugger), nameof(finalizer)));
107+
}
108+
public static void AddHandler(ExceptionHandler Handler)
109+
{
110+
handler += Handler;
111+
}
112+
public delegate void ExceptionHandler(Exception Exception, MethodBase Method);
113+
public static event ExceptionHandler handler;
114+
}
115+
static readonly Harmony Patcher = new Harmony(Others.harmony_id);
116+
public static readonly LogDebugger Logger = new();
117+
public static readonly ProfilerDebugger Profiler = new();
118+
public static readonly ExceptionDebugger ExceptionHandler = new();
119+
static readonly Func<MethodBase, bool> Default = _ => true;
120+
static readonly Func<MethodBase, bool> Attribute = method => method.IsDefined(typeof(DebugAttribute), true) || method.DeclaringType?.IsDefined(typeof(DebugAttribute), true) == true;
45121
}

services/LogService.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,21 @@ public static void LogInfo(string message)
197197
}
198198
}
199199
/// <summary>
200+
/// Log message without [NML] prefix
201+
/// </summary>
202+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
203+
public static void Log(string message)
204+
{
205+
if (Others.unity_player_enabled)
206+
{
207+
UnityEngine.Debug.Log(message);
208+
}
209+
else
210+
{
211+
System.Console.WriteLine(message);
212+
}
213+
}
214+
/// <summary>
200215
/// Log StackTrace from where call this method with [NML] prefix as Info
201216
/// </summary>
202217
[MethodImpl(MethodImplOptions.AggressiveInlining)]

0 commit comments

Comments
 (0)