The 2026-07-29 Coldeve session 3 stuck the player in the portal tunnel forever: generation 2 (Town Network, 0x00070156) published render but composites/collision never became ready, and the reveal latch correctly held the tunnel. The composite warmup queue in WbDrawDispatcher has exactly two permanent-stall shapes - a GfxObj id that never resolves (silent load failure, e.g. custom-server content absent from the baked pak) or an upload budget that never reopens - and they are indistinguishable from the reveal log alone. ACDREAM_PROBE_REVEAL=1 (NetDiagnostics.ProbeReveal) now emits one [composite-warmup] STALL line per second while warmup blocks a reveal: pending count, queue depth, scan state, upload-budget gate, and the first four pending GfxObj ids. Zero cost when off. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
48 lines
2.3 KiB
C#
48 lines
2.3 KiB
C#
namespace AcDream.Core.Net;
|
|
|
|
/// <summary>
|
|
/// Diagnostic owner for the <c>ACDREAM_PROBE_NET</c> probe family (#260).
|
|
/// Read once at startup, following the <c>PhysicsDiagnostics</c> pattern.
|
|
///
|
|
/// <para>
|
|
/// When enabled, three probe line families are emitted:
|
|
/// <list type="bullet">
|
|
/// <item><c>[net-out]</c> — one line per outbound reliable game message at the
|
|
/// <c>WorldSession.SendGameMessage</c> chokepoint: opcode, game-action type +
|
|
/// sequence (when the body is a 0xF7B1 GameAction), fragment/packet sequence,
|
|
/// managed thread id, and session state. An exception escaping the wire write
|
|
/// additionally emits <c>[net-out-EX]</c> via an exception filter (log
|
|
/// without catching — behavior is unchanged).</item>
|
|
/// <item><c>[net-tick]</c> — a once-per-second cadence summary from
|
|
/// <c>WorldSession.Tick</c>: inbound datagrams/s, remaining queue depth,
|
|
/// budget-break count, worst inter-tick gap (= worst frame stall as seen by
|
|
/// the net pump), outbound sends/s, and acks/s.</item>
|
|
/// <item><c>[cmd-gate]</c> — one line per generation-gated runtime command
|
|
/// REJECTION in <c>CurrentGameRuntimeCommandAdapter.Validate</c> (status,
|
|
/// expected vs view generation, lifecycle, IsInWorld) plus the combat-toggle
|
|
/// result. These rejections are otherwise completely silent, which is what
|
|
/// let #260's wedge hide.</item>
|
|
/// </list>
|
|
/// Zero steady-state cost when off: every site is behind this single bool.
|
|
/// </para>
|
|
/// </summary>
|
|
public static class NetDiagnostics
|
|
{
|
|
/// <summary>
|
|
/// <c>ACDREAM_PROBE_NET=1</c> — #260 outbound/command-gate probe family.
|
|
/// </summary>
|
|
public static bool ProbeNet { get; set; } =
|
|
Environment.GetEnvironmentVariable("ACDREAM_PROBE_NET") == "1";
|
|
|
|
/// <summary>
|
|
/// <c>ACDREAM_PROBE_REVEAL=1</c> — #260 reveal-stall probe: while a
|
|
/// reveal destination's composite warmup is incomplete, emit one
|
|
/// <c>[composite-warmup]</c> line per second naming the pending queue
|
|
/// depth, scan state, upload-budget gate, and the first few unresolved
|
|
/// GfxObj ids. The two permanent-stall shapes (a mesh id that never
|
|
/// resolves vs. an upload budget that never reopens) are otherwise
|
|
/// indistinguishable and invisible.
|
|
/// </summary>
|
|
public static bool ProbeReveal { get; set; } =
|
|
Environment.GetEnvironmentVariable("ACDREAM_PROBE_REVEAL") == "1";
|
|
}
|