mirror of
https://github.com/DorkSquadRR/DorkNet.git
synced 2026-10-25 15:08:47 -07:00
feat: Add DorkNet.DebugMod for optional diagnostic features and improved debugging capabilities
This commit is contained in:
@@ -90,6 +90,15 @@ public class Mod : MelonMod
|
|||||||
public static string[] DevCommands = Array.Empty<string>();
|
public static string[] DevCommands = Array.Empty<string>();
|
||||||
public static bool DiagnoseDevMenu = false;
|
public static bool DiagnoseDevMenu = false;
|
||||||
public static bool EnableBuiltInDevDebugTools = false;
|
public static bool EnableBuiltInDevDebugTools = false;
|
||||||
|
// Master switch for the verbose, non-essential DIAGNOSTIC patches
|
||||||
|
// (HTTP header tracing, join/quit traces, studio traces, the deep
|
||||||
|
// RegisterDiagnostics path). OFF by default so the shipping client
|
||||||
|
// mod installs only the patches needed to connect + survive
|
||||||
|
// anti-cheat — the safest possible footprint. Turned ON automatically
|
||||||
|
// when DorkNet.DebugMod.dll is present in the Mods folder (drop it in
|
||||||
|
// to debug, remove it to ship), or by "EnableDiagnostics": true in
|
||||||
|
// the config. Core connectivity/anti-cheat patches are NEVER gated.
|
||||||
|
public static bool EnableDiagnostics = false;
|
||||||
|
|
||||||
// ── Desktop Screen Sharing gadget FPS ──
|
// ── Desktop Screen Sharing gadget FPS ──
|
||||||
// RecRoom.Tools.Productivity.DesktopScreenSharingDisplay broadcasts
|
// RecRoom.Tools.Productivity.DesktopScreenSharingDisplay broadcasts
|
||||||
@@ -167,7 +176,11 @@ public class Mod : MelonMod
|
|||||||
"NotifyServerCertificate",
|
"NotifyServerCertificate",
|
||||||
prefix: nameof(TlsPatches.NotifyServerCertificate_Prefix));
|
prefix: nameof(TlsPatches.NotifyServerCertificate_Prefix));
|
||||||
}
|
}
|
||||||
RegisterQuitTracePatches(logMisses: true);
|
// Anti-tamper / ToxMod / file-hash-checker are anti-cheat BYPASS
|
||||||
|
// patches — core, always on, or the modded client gets kicked.
|
||||||
|
// Quit-trace is pure diagnostics, so it's gated.
|
||||||
|
if (Cfg.EnableDiagnostics)
|
||||||
|
RegisterQuitTracePatches(logMisses: true);
|
||||||
RegisterAntiTamperCallbackPatches(logMisses: true);
|
RegisterAntiTamperCallbackPatches(logMisses: true);
|
||||||
RegisterToxModPatches(logMisses: true);
|
RegisterToxModPatches(logMisses: true);
|
||||||
PatchFileHashCheckerCallback();
|
PatchFileHashCheckerCallback();
|
||||||
@@ -206,7 +219,8 @@ public class Mod : MelonMod
|
|||||||
Log.Msg($"[questsize] armed: target {Cfg.QuestMaxTeamSize} for [{string.Join(", ", Cfg.QuestMaxTeamSizeRooms)}]");
|
Log.Msg($"[questsize] armed: target {Cfg.QuestMaxTeamSize} for [{string.Join(", ", Cfg.QuestMaxTeamSizeRooms)}]");
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterStudioTracePatches();
|
if (Cfg.EnableDiagnostics)
|
||||||
|
RegisterStudioTracePatches();
|
||||||
|
|
||||||
if (Cfg.EnableBuiltInDevDebugTools)
|
if (Cfg.EnableBuiltInDevDebugTools)
|
||||||
RegisterBuiltInDevDebugTools();
|
RegisterBuiltInDevDebugTools();
|
||||||
@@ -525,7 +539,10 @@ public class Mod : MelonMod
|
|||||||
args: new[] { ResolveType("BestHTTP.HTTPRequest") ?? typeof(object) },
|
args: new[] { ResolveType("BestHTTP.HTTPRequest") ?? typeof(object) },
|
||||||
prefix: nameof(UriPatches.HttpManagerSendRequestObject_Prefix));
|
prefix: nameof(UriPatches.HttpManagerSendRequestObject_Prefix));
|
||||||
|
|
||||||
RegisterHttpDiagnostics();
|
// HTTP header/callback tracing is pure diagnostics (and the noisiest
|
||||||
|
// thing in the log) — only install it when diagnostics are enabled.
|
||||||
|
if (Cfg.EnableDiagnostics)
|
||||||
|
RegisterHttpDiagnostics();
|
||||||
_networkPatchesRegistered = complete;
|
_networkPatchesRegistered = complete;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -697,7 +714,7 @@ public class Mod : MelonMod
|
|||||||
Log.Msg("[lifecycle] first OnUpdate tick (Unity frame loop is live)");
|
Log.Msg("[lifecycle] first OnUpdate tick (Unity frame loop is live)");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_quitTraceGameComplete && ++_quitTraceRetryFrame >= 300)
|
if (Cfg.EnableDiagnostics && !_quitTraceGameComplete && ++_quitTraceRetryFrame >= 300)
|
||||||
{
|
{
|
||||||
_quitTraceRetryFrame = 0;
|
_quitTraceRetryFrame = 0;
|
||||||
RegisterQuitTracePatches(logMisses: false);
|
RegisterQuitTracePatches(logMisses: false);
|
||||||
@@ -734,6 +751,22 @@ public class Mod : MelonMod
|
|||||||
var userData = ResolveUserDataDirectory();
|
var userData = ResolveUserDataDirectory();
|
||||||
Directory.CreateDirectory(userData);
|
Directory.CreateDirectory(userData);
|
||||||
DiagnosticsLogPath = Path.Combine(userData, "dorknet-diagnostics.log");
|
DiagnosticsLogPath = Path.Combine(userData, "dorknet-diagnostics.log");
|
||||||
|
|
||||||
|
// Auto-enable diagnostics when the separate DorkNet.DebugMod.dll is
|
||||||
|
// dropped in alongside this mod. Done before the config read (and
|
||||||
|
// before the no-config-file early return) so presence alone is
|
||||||
|
// enough — no config edit required to debug.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var modsDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||||
|
if (modsDir != null && File.Exists(Path.Combine(modsDir, "DorkNet.DebugMod.dll")))
|
||||||
|
{
|
||||||
|
Cfg.EnableDiagnostics = true;
|
||||||
|
Log.Msg("[config] DorkNet.DebugMod.dll present → diagnostics ENABLED");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { /* presence detection is best-effort */ }
|
||||||
|
|
||||||
var path = Path.Combine(userData, "dorknet-clientmod.json");
|
var path = Path.Combine(userData, "dorknet-clientmod.json");
|
||||||
if (!File.Exists(path))
|
if (!File.Exists(path))
|
||||||
{
|
{
|
||||||
@@ -749,6 +782,9 @@ public class Mod : MelonMod
|
|||||||
if (TryGetConfigValue(r, "DebugConsoleToggleKey", out v)) Cfg.DebugConsoleToggleKey = v.GetString() ?? Cfg.DebugConsoleToggleKey;
|
if (TryGetConfigValue(r, "DebugConsoleToggleKey", out v)) Cfg.DebugConsoleToggleKey = v.GetString() ?? Cfg.DebugConsoleToggleKey;
|
||||||
if (TryGetConfigValue(r, "DiagnoseDevMenu", out v)) Cfg.DiagnoseDevMenu = v.GetBoolean();
|
if (TryGetConfigValue(r, "DiagnoseDevMenu", out v)) Cfg.DiagnoseDevMenu = v.GetBoolean();
|
||||||
if (TryGetConfigValue(r, "EnableBuiltInDevDebugTools", out v)) Cfg.EnableBuiltInDevDebugTools = v.GetBoolean();
|
if (TryGetConfigValue(r, "EnableBuiltInDevDebugTools", out v)) Cfg.EnableBuiltInDevDebugTools = v.GetBoolean();
|
||||||
|
// Config can also enable diagnostics; OR with the debug-mod
|
||||||
|
// presence check above so either path turns them on.
|
||||||
|
if (TryGetConfigValue(r, "EnableDiagnostics", out v)) Cfg.EnableDiagnostics |= v.GetBoolean();
|
||||||
if (TryGetConfigValue(r, "DevCommands", out v) && v.ValueKind == JsonValueKind.Array)
|
if (TryGetConfigValue(r, "DevCommands", out v) && v.ValueKind == JsonValueKind.Array)
|
||||||
{
|
{
|
||||||
var commands = new List<string>();
|
var commands = new List<string>();
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
// DorkNet.DebugMod — opt-in debugging switch for DorkNet.ClientMod.
|
||||||
|
//
|
||||||
|
// This mod intentionally does almost nothing on its own. Its job is to
|
||||||
|
// EXIST: when its DLL sits in the Mods folder next to DorkNet.ClientMod.dll,
|
||||||
|
// the ClientMod detects it at startup (Cfg.EnableDiagnostics) and installs
|
||||||
|
// its verbose diagnostic patches — HTTP header/callback tracing, join/quit
|
||||||
|
// /studio traces, and the deep RegisterDiagnostics probes. Remove this DLL
|
||||||
|
// to ship a quiet, minimal client that only carries the connect + anti-cheat
|
||||||
|
// patches.
|
||||||
|
//
|
||||||
|
// Keeping the switch as a separate assembly (rather than a config flag baked
|
||||||
|
// into the shipping mod) means the diagnostics literally cannot turn
|
||||||
|
// themselves on in a normal install — you have to deliberately drop this
|
||||||
|
// file in. That is the "as safe as possible" default the main mod wants.
|
||||||
|
|
||||||
|
using MelonLoader;
|
||||||
|
|
||||||
|
[assembly: MelonInfo(typeof(DorkNet.DebugMod.DebugMod), "DorkNet DebugMod", "1.0.0", "Dork Squad")]
|
||||||
|
[assembly: MelonGame(null, null)]
|
||||||
|
|
||||||
|
namespace DorkNet.DebugMod;
|
||||||
|
|
||||||
|
public class DebugMod : MelonMod
|
||||||
|
{
|
||||||
|
public override void OnInitializeMelon()
|
||||||
|
{
|
||||||
|
LoggerInstance.Msg(
|
||||||
|
"=== DorkNet DebugMod present — DorkNet.ClientMod diagnostics are ENABLED. " +
|
||||||
|
"Remove DorkNet.DebugMod.dll from Mods to ship a quiet client. ===");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
DorkNet.DebugMod — the opt-in debugging companion to DorkNet.ClientMod.
|
||||||
|
|
||||||
|
The shipping ClientMod installs ONLY the patches needed to connect and
|
||||||
|
survive anti-cheat; all of its verbose diagnostic patches (HTTP header
|
||||||
|
tracing, join/quit/studio traces, the deep RegisterDiagnostics path) are
|
||||||
|
gated OFF by default. Dropping THIS dll into the Mods folder next to
|
||||||
|
DorkNet.ClientMod.dll flips Cfg.EnableDiagnostics on (the ClientMod
|
||||||
|
detects this dll's presence at startup), turning all of that tracing
|
||||||
|
back on. Remove it to ship a quiet, minimal client.
|
||||||
|
|
||||||
|
Build: dotnet build DorkNet.DebugMod/DorkNet.DebugMod.csproj -c Release
|
||||||
|
-->
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework Condition="'$(TargetFramework)' == ''">net6.0</TargetFramework>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<RootNamespace>DorkNet.DebugMod</RootNamespace>
|
||||||
|
<AssemblyName>DorkNet.DebugMod</AssemblyName>
|
||||||
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
|
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
|
||||||
|
<NoWarn>$(NoWarn);CS8602;CS8604;CS0436</NoWarn>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!-- Reuse the MelonLoader the ClientMod build already downloads. -->
|
||||||
|
<PropertyGroup>
|
||||||
|
<MelonLoaderDir Condition="'$(MelonLoaderDir)' == ''">$(MSBuildThisFileDirectory)..\DorkNet.ClientMod\build\melonloader\MelonLoader\net6</MelonLoaderDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="MelonLoader">
|
||||||
|
<HintPath>$(MelonLoaderDir)\MelonLoader.dll</HintPath>
|
||||||
|
<Private>false</Private>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -172,9 +172,18 @@ export function Rooms() {
|
|||||||
<td className="px-4 py-2.5 text-right text-ink-200 tabular-nums">{r.blobCount}</td>
|
<td className="px-4 py-2.5 text-right text-ink-200 tabular-nums">{r.blobCount}</td>
|
||||||
<td className="px-4 py-2.5 text-right whitespace-nowrap">
|
<td className="px-4 py-2.5 text-right whitespace-nowrap">
|
||||||
<Link to={`/rooms/${r.id}`} className="btn-ghost text-xs">Manage</Link>
|
<Link to={`/rooms/${r.id}`} className="btn-ghost text-xs">Manage</Link>
|
||||||
<button onClick={() => setPendingDelete(r)} className="btn-ghost text-xs text-danger ml-1" title="Soft archive">
|
<button onClick={() => setPendingDelete(r)} className="btn-ghost text-xs text-danger ml-1" title="Soft archive (reversible)">
|
||||||
<Trash />
|
<Trash />
|
||||||
</button>
|
</button>
|
||||||
|
{!r.isDormRoom && (
|
||||||
|
<button
|
||||||
|
onClick={() => setPendingPurge(r)}
|
||||||
|
className="btn-ghost text-xs text-danger ml-1"
|
||||||
|
title="Purge — permanent hard delete (requires typing the room name twice)"
|
||||||
|
>
|
||||||
|
Purge
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
|
|||||||
Reference in New Issue
Block a user