fix #435 (part 2, closes it): attribute the unowned probes — delete 7, reclassify 8, restore 1

Part 1 deleted probes whose owning issues were closed. These 14 named no
issue at all, so each was traced to its introducing commit
(git log -S) instead of guessed at. Attribution split them three ways:

DELETED (7, investigations closed): ACDREAM_A8_DUMP_PV and
ACDREAM_DUMP_LIVE_SPAWNS (Phase A8), ACDREAM_DUMP_CLOTHING (#37),
ACDREAM_DUMP_EDGE_SLIDE (#32), ACDREAM_DUMP_STEPUP (L.2.3d-f),
ACDREAM_DUMP_VENDOR (the vendor campaign, 25 call sites across 8 files),
ACDREAM_DUMP_VITALS (#5, four independent read sites). VendorDiagnostics.cs
went entirely.

RECLASSIFIED (8, tools misfiled as probes): the DUMP_CELLS/DUMP_GFXOBJS
fixture-extraction family (replay-harness tooling with a roundtrip test),
PROBE_CELL (standing cell-transit tracer, pair of the permanent
PROBE_RESOLVE), DUMP_SKY and HIDE_PART (generic isolation tools), and
DUMP_STEEP_ROOF — which looked like an L.4 relic but observes LIVE
divergence-register row AD-56; deleting it would have removed the only
runtime lens on an active divergence. All moved to Permanent diagnostics
with their attribution recorded.

RESTORED (1): ACDREAM_DUMP_MOVE_TRUTH was deleted and un-deleted the same
day. It is not a probe — the canonical nine-stop soak
(run-connected-r6-soak.ps1) hard-fails every destination without its
'move-truth OUT' records, with a message that would misdirect the next
operator. Under the no-workarounds rule the gate's mechanism is restored,
not left broken with an IOU (#437, closed). Process lesson recorded on
both issues: a closed owning issue is NOT sufficient to delete a probe —
grep tools/ and the contract tests for consumers first.

Also lands the owner-requested default-off invariant: every diagnostic in
the codebase is inert until its env var is explicitly set. Exactly four
flags default ON and none is a diagnostic — RETAIL_CHASE, CAMERA_COLLIDE,
CAMERA_ALIGN_SLOPE, RETAIL_CLOSE_DEGRADES are retail behaviors wearing an
A/B off-switch. That set is now FROZEN by
LaunchOptionsDocumentationTests.OnlyTheFourRetailBehaviorFlagsDefaultOn;
docs/launch-options.md's Conventions and CLAUDE.md state the rule, and
CLAUDE.md now binds future probes to a documented row in the same commit.

The client reads 137 environment variables (161 at audit start); 40
temporary probes remain, every one attributed. Full hermetic suite 15,322
passed / 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-24 12:32:42 +02:00
parent 0c5057c9ff
commit c1e6e3da44
26 changed files with 256 additions and 693 deletions

View file

@ -562,8 +562,7 @@ internal sealed class SessionPlayerCompositionPhase
d.EntityObjects,
teardown,
d.PlayerIdentity,
dormantLiveEntities,
d.Options.DumpLiveSpawns ? d.Log : null);
dormantLiveEntities);
// 2026-08-08 vendor-approach root cause: the local player's
// publication-chain host resolves moveto/sticky targets through
// RuntimePhysicsState.ResolveObjectTableHost. Bind the graphical
@ -709,7 +708,6 @@ internal sealed class SessionPlayerCompositionPhase
d.PlayerIdentity,
deletion,
dormantLiveEntities,
d.Options.DumpLiveSpawns ? d.Log : null,
firstEntryDrive,
acceptedPositionDrive);
bindings.Adopt(

View file

@ -61,14 +61,6 @@ internal sealed class PlayerInteractionMovementSink(
Height = approach.TargetHeight,
};
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] BeginApproach guid=0x{approach.Target.ServerGuid:X8} "
+ $"movementType={movement.Type} distanceToObject={parameters.DistanceToObject} "
+ $"canCharge={parameters.CanCharge} target=0x{movement.ObjectId:X8}");
}
// PerformMovement cancels at its head. Do it explicitly before the
// intent is armed so cancellation of the preceding move cannot clear
// the new request; the internal second call is then a retail no-op.

View file

@ -181,11 +181,6 @@ internal sealed class SelectionInteractionController
// ships with it.
if (useImmediately && !_query.IsWieldedByPlayer(guid))
{
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] route=dblclick-world PickAndStoreSelection guid=0x{guid:X8} enqueue=Activate");
}
EnqueueIdentityBound(
RuntimeQueuedInteractionKind.Activate,
guid,
@ -221,11 +216,6 @@ internal sealed class SelectionInteractionController
_toast?.Invoke("Nothing selected");
return;
}
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] route=keyboard-use UseCurrentSelection guid=0x{selected:X8} enqueue=Use");
}
EnqueueIdentityBound(
RuntimeQueuedInteractionKind.Use,
selected,
@ -292,22 +282,10 @@ internal sealed class SelectionInteractionController
bool ownedByPlayer = _items.IsOwnedByPlayer(serverGuid);
bool useable = ownedByPlayer || _query.IsUseable(serverGuid);
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] RequestUse entry guid=0x{serverGuid:X8} ownedByPlayer={ownedByPlayer} useable={useable}");
}
if (useable
&& _query.TryGetApproach(serverGuid, out InteractionApproach approach)
&& !approach.IsCloseRange)
{
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] RequestUse guid=0x{serverGuid:X8} branch=approach-armed useRadius={approach.UseRadius} isCloseRange={approach.IsCloseRange}");
}
// Genuinely out of range (a real walk, not just a turn) —
// mirror SendPickup's arrival-gated shape: arm the transaction
// on the approach token BEFORE the movement starts (so a
@ -327,17 +305,7 @@ internal sealed class SelectionInteractionController
token.ControllerLifetime,
token.ApproachGeneration),
out _);
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] TryArmPostArrivalUse guid=0x{serverGuid:X8} armed={armed} approachToken=({token.ControllerLifetime},{token.ApproachGeneration})");
}
});
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] BeginApproach-result guid=0x{serverGuid:X8} started={started} armed={armed} stopDistance={approach.UseRadius} target=0x{approach.Target.ServerGuid:X8}");
}
if (!started || !armed)
{
// Release whatever got captured (or the caller's own
@ -360,11 +328,6 @@ internal sealed class SelectionInteractionController
// — keep retail's immediate send; ACE's own "already within use
// distance" branch (Player_Move.cs:65-87) calls back synchronously,
// so there is no arrival gap to race here.
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] RequestUse guid=0x{serverGuid:X8} branch=immediate-dispatch ownedByPlayer={ownedByPlayer} useable={useable}");
}
RuntimeInteractionDispatchResult result =
_transactions.TryDispatchUse(
serverGuid,
@ -373,11 +336,6 @@ internal sealed class SelectionInteractionController
reservation,
_transport,
out uint sequence);
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] RequestUse guid=0x{serverGuid:X8} TryDispatchUse verdict={result} seq={sequence}");
}
if (result == RuntimeInteractionDispatchResult.NotInWorld)
_toast?.Invoke("Not in world");
if (result == RuntimeInteractionDispatchResult.Dispatched)
@ -609,22 +567,6 @@ internal sealed class SelectionInteractionController
RuntimePendingUse pending,
bool accepted)
{
if (VendorDiagnostics.DumpVendorEnabled)
{
// Diagnostic-only re-query — TryGetApproach is a pure read with
// no side effects, so an extra call here (gated off in
// production) cannot change RequestUse's own dispatch outcome.
string distanceText = "n/a";
if (_query.TryGetApproach(pending.ServerGuid, out InteractionApproach diagApproach))
{
float dx = diagApproach.Target.Entity.Position.X - diagApproach.Player.Position.X;
float dy = diagApproach.Target.Entity.Position.Y - diagApproach.Player.Position.Y;
distanceText = MathF.Sqrt(dx * dx + dy * dy).ToString("F2");
}
Console.WriteLine(
$"[vendor-diag] HandleUseApproachCompletion guid=0x{pending.ServerGuid:X8} accepted={accepted} playerToTargetDist={distanceText}");
}
if (!accepted)
{
pending.Reservation?.CancelBeforeDispatch();

View file

@ -571,12 +571,6 @@ internal sealed class WorldSelectionQuery
bool haveSpawn = _liveEntities.TryGetSnapshot(serverGuid, out var spawn);
bool fromWire = haveSpawn && spawn.UseRadius is > 0f;
float radius = fromWire ? spawn.UseRadius!.Value : DefaultUseRadius;
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] GetUseRadius guid=0x{serverGuid:X8} radius={radius} "
+ $"source={(fromWire ? "wire" : "fallback-0.6")}");
}
return radius;
}
}

View file

@ -58,17 +58,6 @@ internal sealed class DatLiveEntityProjectionMaterializer
/// </summary>
private readonly RuntimeWorldTransitState _transit;
private int _received;
private int _hydrated;
private int _noPosition;
private int _noSetup;
private int _missingSetup;
private int _noMesh;
private int _noCycle;
private int _zeroFramerate;
private int _singleFrame;
private int _missingPartFrames;
public DatLiveEntityProjectionMaterializer(
RuntimeOptions options,
IDatReaderWriter dats,
@ -116,16 +105,6 @@ internal sealed class DatLiveEntityProjectionMaterializer
public void ResetSessionState()
{
_received = 0;
_hydrated = 0;
_noPosition = 0;
_noSetup = 0;
_missingSetup = 0;
_noMesh = 0;
_noCycle = 0;
_zeroFramerate = 0;
_singleFrame = 0;
_missingPartFrames = 0;
}
public bool TryMaterialize(
@ -157,18 +136,10 @@ internal sealed class DatLiveEntityProjectionMaterializer
if (appearanceUpdate is not null && expectedRecord is null)
return false;
_received++;
bool dumpLiveSpawns = _options.DumpLiveSpawns;
DumpSpawn(canonicalSpawn, dumpLiveSpawns);
if (!_origin.IsKnown)
return false;
if (canonicalSpawn.Position is null || canonicalSpawn.SetupTableId is null)
{
if (canonicalSpawn.Position is null)
_noPosition++;
else
_noSetup++;
return false;
}
@ -216,13 +187,6 @@ internal sealed class DatLiveEntityProjectionMaterializer
_collisionAssets.CacheSetup(canonicalSpawn.SetupTableId.Value, setup);
if (setup is null)
{
_missingSetup++;
if (dumpLiveSpawns)
{
Console.WriteLine(
$"live: DROP setup dat 0x{canonicalSpawn.SetupTableId.Value:X8} missing "
+ $"(guid=0x{canonicalSpawn.Guid:X8})");
}
return false;
}
@ -248,14 +212,6 @@ internal sealed class DatLiveEntityProjectionMaterializer
List<MeshRef> flattened = [.. SetupMesh.Flatten(setup, idleFrame)];
IReadOnlyList<CreateObject.AnimPartChange> animPartChanges =
canonicalSpawn.AnimPartChanges ?? Array.Empty<CreateObject.AnimPartChange>();
bool dumpClothing = _options.DumpClothing && setup.Parts.Count >= 10;
DumpClothingHeader(
canonicalSpawn,
setup,
flattened,
idleFrame,
animPartChanges,
dumpClothing);
foreach (CreateObject.AnimPartChange change in animPartChanges)
{
@ -273,17 +229,14 @@ internal sealed class DatLiveEntityProjectionMaterializer
baseId => ResolveCollisionPart(baseId));
if (_options.RetailCloseDegrades && IsIssue47HumanoidSetup(setup))
ApplyRetailCloseDegrades(flattened, dumpClothing);
ApplyRetailCloseDegrades(flattened);
IReadOnlyList<CreateObject.TextureChange> textureChanges =
canonicalSpawn.TextureChanges ?? Array.Empty<CreateObject.TextureChange>();
Dictionary<int, Dictionary<uint, uint>>? surfaceOverrides =
ResolveSurfaceOverrides(
canonicalSpawn,
flattened,
textureChanges,
dumpClothing,
dumpLiveSpawns);
textureChanges);
float scale = canonicalSpawn.ObjScale ?? 1f;
Matrix4x4 scaleMatrix = Matrix4x4.CreateScale(scale);
@ -294,7 +247,6 @@ internal sealed class DatLiveEntityProjectionMaterializer
var indexedPartAvailable = new bool[flattened.Count];
var animatedPartTemplate = new LiveAnimationPartTemplate[flattened.Count];
var bounds = new LocalBoundsAccumulator();
int clothingTriangles = 0;
for (int partIndex = 0; partIndex < flattened.Count; partIndex++)
{
@ -318,23 +270,10 @@ internal sealed class DatLiveEntityProjectionMaterializer
drawable);
if (gfx is null)
{
if (dumpClothing)
Console.WriteLine($" EMIT part={partIndex:D2} gfx=0x{part.GfxObjId:X8} GFXOBJ_DAT_MISSING -> 0 tris");
continue;
}
_collisionAssets.CacheGfxObj(part.GfxObjId, gfx);
if (dumpClothing)
{
var subMeshes = GfxObjMesh.Build(gfx, _dats);
int triangles = 0;
foreach (var subMesh in subMeshes)
triangles += subMesh.Indices.Length / 3;
clothingTriangles += triangles;
Console.WriteLine(
$" EMIT part={partIndex:D2} gfx=0x{part.GfxObjId:X8} "
+ $"subMeshes={subMeshes.Count} tris={triangles}");
}
if (GfxObjBounds.Get(gfx) is { } partBounds)
bounds.Add(transform, partBounds);
@ -346,21 +285,8 @@ internal sealed class DatLiveEntityProjectionMaterializer
if (meshRefs.Count == 0)
{
_noMesh++;
if (dumpLiveSpawns)
{
Console.WriteLine(
$"live: DROP no mesh refs from setup 0x{canonicalSpawn.SetupTableId.Value:X8} "
+ $"(guid=0x{canonicalSpawn.Guid:X8})");
}
return false;
}
if (dumpClothing)
{
Console.WriteLine(
$" TOTAL tris={clothingTriangles} meshRefs={meshRefs.Count} "
+ $"(parts.Count={flattened.Count})");
}
PaletteOverride? paletteOverride = CreatePaletteOverride(canonicalSpawn);
PartOverride[] partOverrides = CreatePartOverrides(animPartChanges);
@ -456,7 +382,6 @@ internal sealed class DatLiveEntityProjectionMaterializer
indexedPartAvailable,
animatedPartTemplate,
bounds,
dumpLiveSpawns,
expectedCreateIntegrationVersion,
synchronizeAnimation: supersessionRecovery);
}
@ -477,9 +402,7 @@ internal sealed class DatLiveEntityProjectionMaterializer
return slotZeroId;
}
private void ApplyRetailCloseDegrades(
List<MeshRef> parts,
bool dumpClothing)
private void ApplyRetailCloseDegrades(List<MeshRef> parts)
{
for (int partIndex = 0; partIndex < parts.Count; partIndex++)
{
@ -495,33 +418,13 @@ internal sealed class DatLiveEntityProjectionMaterializer
}
parts[partIndex] = new MeshRef(resolvedId, part.PartTransform);
if (dumpClothing)
{
Console.WriteLine(
$" DEGRADE part={partIndex:D2} gfx=0x{part.GfxObjId:X8} "
+ $"-> close=0x{resolvedId:X8}");
}
}
}
private Dictionary<int, Dictionary<uint, uint>>? ResolveSurfaceOverrides(
WorldSession.EntitySpawn spawn,
IReadOnlyList<MeshRef> parts,
IReadOnlyList<CreateObject.TextureChange> textureChanges,
bool dumpClothing,
bool dumpLiveSpawns)
IReadOnlyList<CreateObject.TextureChange> textureChanges)
{
if (dumpClothing)
{
Console.WriteLine($" TextureChanges count={textureChanges.Count}");
foreach (CreateObject.TextureChange change in textureChanges)
{
Console.WriteLine(
$" TC part={change.PartIndex:D2} oldTex=0x{change.OldTexture:X8} "
+ $"-> newTex=0x{change.NewTexture:X8}");
}
}
if (textureChanges.Count == 0)
return null;
@ -536,8 +439,6 @@ internal sealed class DatLiveEntityProjectionMaterializer
oldToNew[change.OldTexture] = change.NewTexture;
}
bool statueDiagnostic = dumpLiveSpawns
&& spawn.Name?.Contains("Statue", StringComparison.OrdinalIgnoreCase) == true;
var result = new Dictionary<int, Dictionary<uint, uint>>();
for (int partIndex = 0; partIndex < parts.Count; partIndex++)
{
@ -547,12 +448,6 @@ internal sealed class DatLiveEntityProjectionMaterializer
GfxObj? gfx = _dats.Get<GfxObj>(parts[partIndex].GfxObjId);
if (gfx is null)
{
if (statueDiagnostic)
{
Console.WriteLine(
$"live: [STATUE] resolve part={partIndex} "
+ $"GfxObj 0x{parts[partIndex].GfxObjId:X8} missing");
}
continue;
}
_collisionAssets.CacheGfxObj(parts[partIndex].GfxObjId, gfx);
@ -729,7 +624,6 @@ internal sealed class DatLiveEntityProjectionMaterializer
IReadOnlyList<bool> indexedPartAvailable,
IReadOnlyList<LiveAnimationPartTemplate> animatedPartTemplate,
LocalBoundsAccumulator bounds,
bool dumpLiveSpawns,
ulong expectedCreateIntegrationVersion,
bool synchronizeAnimation)
{
@ -835,7 +729,6 @@ internal sealed class DatLiveEntityProjectionMaterializer
_worldEvents.UpsertCurrent(snapshot);
if (_runtime.TryMarkWorldSpawnPublished(spawn.Guid))
_worldEvents.FireEntitySpawned(snapshot);
_hydrated++;
if (!_runtime.IsCurrentCreateIntegration(
expectedRecord,
@ -921,18 +814,6 @@ internal sealed class DatLiveEntityProjectionMaterializer
return false;
}
if (dumpLiveSpawns && _received % 20 == 0)
{
Console.WriteLine(
$"live: animated={_runtime.AnimationRuntimeCount} "
+ $"animReject: noCycle={_noCycle} fr0={_zeroFramerate} "
+ $"1frame={_singleFrame} partFrames={_missingPartFrames}");
Console.WriteLine(
$"live: summary recv={_received} hydrated={_hydrated} "
+ $"drops: noPos={_noPosition} noSetup={_noSetup} "
+ $"setupMissing={_missingSetup} noMesh={_noMesh}");
}
return _runtime.IsCurrentCreateIntegration(
expectedRecord,
expectedCreateIntegrationVersion);
@ -961,18 +842,6 @@ internal sealed class DatLiveEntityProjectionMaterializer
spawn,
idleCycle);
}
if (!retainedAnimation)
{
if (idleCycle is null)
_noCycle++;
else if (idleCycle.Framerate == 0f)
_zeroFramerate++;
else if (idleCycle.HighFrame <= idleCycle.LowFrame)
_singleFrame++;
else if (idleCycle.Animation.PartFrames.Count <= 1)
_missingPartFrames++;
}
if (!retainedAnimation
&& idleCycle is not null
&& idleCycle.Framerate != 0f
@ -1159,56 +1028,6 @@ internal sealed class DatLiveEntityProjectionMaterializer
: null;
}
private void DumpSpawn(WorldSession.EntitySpawn spawn, bool enabled)
{
if (!enabled)
return;
string position = spawn.Position is { } p
? $"({p.PositionX:F1},{p.PositionY:F1},{p.PositionZ:F1})@0x{p.LandblockId:X8}"
: "no-pos";
string setup = spawn.SetupTableId is { } setupId
? $"0x{setupId:X8}"
: "no-setup";
string physicsTable = spawn.Physics?.PhysicsScriptTableId is { } tableId
? $"0x{tableId:X8}"
: "no-petable";
string name = spawn.Name is { Length: > 0 } foundName
? $"\"{foundName}\""
: "no-name";
string itemType = spawn.ItemType is { } foundItemType
? $"0x{foundItemType:X8}"
: "no-itemtype";
Console.WriteLine(
$"live: spawn guid=0x{spawn.Guid:X8} name={name} setup={setup} pos={position} "
+ $"petable={physicsTable} itemType={itemType} "
+ $"animParts={spawn.AnimPartChanges?.Count ?? 0} "
+ $"texChanges={spawn.TextureChanges?.Count ?? 0} "
+ $"subPalettes={spawn.SubPalettes?.Count ?? 0}");
}
private void DumpClothingHeader(
WorldSession.EntitySpawn spawn,
Setup setup,
IReadOnlyList<MeshRef> flattened,
AnimationFrame? idleFrame,
IReadOnlyList<CreateObject.AnimPartChange> changes,
bool enabled)
{
if (!enabled)
return;
Console.WriteLine(
$"\n=== DUMP_CLOTHING: guid=0x{spawn.Guid:X8} name='{spawn.Name}' "
+ $"setup=0x{setup.Id:X8} setup.Parts.Count={setup.Parts.Count} "
+ $"flatten.Count={flattened.Count} APC={changes.Count} ===");
foreach (CreateObject.AnimPartChange change in changes)
Console.WriteLine($" APC part={change.PartIndex:D2} -> gfx=0x{change.NewModelId:X8}");
Console.WriteLine(
$" basePalette=0x{spawn.BasePaletteId ?? 0:X8} "
+ $"subPalettes={spawn.SubPalettes?.Count ?? 0}");
}
private static bool IsIssue47HumanoidSetup(Setup setup)
{
if (setup.Parts.Count != 34)

View file

@ -265,12 +265,6 @@ public static class PortalVisibilityBuilder
// stands near a doorway plane).
private const float SeedInPlaneEpsilon = 0.0002f;
// TEMP diagnostic (Phase A8.F visual-gate triage; strip after): ACDREAM_A8_DUMP_PV=1 dumps the
// local→NDC→clipped portal geometry for the first 2 Build calls per distinct camera cell.
private static readonly bool s_pvDump =
Environment.GetEnvironmentVariable("ACDREAM_A8_DUMP_PV") == "1";
private static readonly Dictionary<uint, int> s_pvDumpCount = new();
/// <summary>
/// #120 observable: total convergence-tripwire firings across both the
/// interior <see cref="Build"/> and the exterior look-in propagation.
@ -386,36 +380,6 @@ public static class PortalVisibilityBuilder
int churnReenqueues = 0;
var churnReciprocal = churnProbe ? new System.Text.StringBuilder(256) : null;
bool pvDump = false;
if (s_pvDump)
{
lock (s_pvDumpCount)
{
s_pvDumpCount.TryGetValue(cameraCell.CellId, out int dc);
if (dc < 2) { s_pvDumpCount[cameraCell.CellId] = dc + 1; pvDump = true; }
}
if (pvDump)
{
Console.WriteLine($"[pv-dump] camCell=0x{cameraCell.CellId:X8} portals={cameraCell.Portals.Count} polyLists={cameraCell.PortalPolygons.Count} vp[M11={viewProj.M11:F3} M22={viewProj.M22:F3} M33={viewProj.M33:F3} M34={viewProj.M34:F3} M43={viewProj.M43:F3} M44={viewProj.M44:F3}]");
// Camera-cell portal census (A8.F triage 2026-05-29): report, for EVERY
// portal, the exact inputs the BFS guards read — BEFORE the guards run, so
// a portal the loop silently `continue`s past is still visible here. An
// empty OUTSIDEVIEW can then be traced to the precise gate: polyLen<3 (empty
// polygon from EnvCellLandblockBuildBuilder), interiorSide=false (camera back-facing the
// portal — a legitimately-empty result, not a bug), or (if both OK) a
// downstream projection/clip failure shown by the EXIT-PROJ/EXIT-CLIP lines.
for (int ci = 0; ci < cameraCell.Portals.Count; ci++)
{
int plen = ci < cameraCell.PortalPolygons.Count
? (cameraCell.PortalPolygons[ci]?.Length ?? -1) : -2;
bool hasPlane = ci < cameraCell.ClipPlanes.Count;
bool interiorSide = !hasPlane || CameraOnInteriorSide(cameraCell, ci, cameraPos);
var n = hasPlane ? cameraCell.ClipPlanes[ci].Normal : Vector3.Zero;
Console.WriteLine($"[pv-dump] CAMPORTAL[{ci}] other=0x{cameraCell.Portals[ci].OtherCellId:X4} polyLen={plen} hasPlane={hasPlane} interiorSide={interiorSide} planeN=({n.X:F3},{n.Y:F3},{n.Z:F3})");
}
}
}
// T2 (BR-4): retail's growth propagation is IN PLACE, never by re-enqueue
// — PView::AddViewToPortals (Ghidra 0x005a52d0, pc:433446): first
// discovery enqueues via InsCellTodoList; growth into a cell whose
@ -481,8 +445,6 @@ public static class PortalVisibilityBuilder
continue;
}
bool dx = pvDump && cell.Portals[i].OtherCellId == 0xFFFF;
// (R-A2b Phase 1 pin, throwaway) Log the side-test inputs for EVERY portal so a back-portal
// traversal (cell=0x..0173 p->0x0171) can be attributed to the side test.
// Strip with the rest of the [pv-trace] apparatus.
@ -505,7 +467,6 @@ public static class PortalVisibilityBuilder
&& !CameraOnInteriorSide(cell, i, cameraPos))
{
trace?.Add($"portal cell=0x{cell.CellId:X8} p{i}->0x{portal.OtherCellId:X4} skip=side");
if (dx) Console.WriteLine($"[pv-dump] EXIT-CULLED(side) cell=0x{cell.CellId:X8} p{i} localN={poly.Length} hasClipPlane={(i < cell.ClipPlanes.Count)}");
continue;
}
@ -526,8 +487,6 @@ public static class PortalVisibilityBuilder
endCount - processedCount,
clippedRegion,
out int clipVerts);
if (dx) Console.WriteLine($"[pv-dump] EXIT-PROJ cell=0x{cell.CellId:X8} p{i} localN={poly.Length} clipN={clipVerts} local0=({poly[0].X:F2},{poly[0].Y:F2},{poly[0].Z:F2})");
if (dx) Console.WriteLine($"[pv-dump] EXIT-CLIP cell=0x{cell.CellId:X8} p{i} currentViewPolys={currentView.Polygons.Count} clipResult={clippedRegion.Count}");
// Empty clip = no flood through this portal, period — retail's empty-GetClip rule
// (polyClipFinish <3 survivors → reject; ClipPortals adds no view). The
@ -544,13 +503,6 @@ public static class PortalVisibilityBuilder
if (portal.OtherCellId == 0xFFFF)
{
if (pvDump)
{
Console.WriteLine($"[pv-dump] EXIT cell=0x{cell.CellId:X8} p{i} localN={poly.Length} clipVerts={clipVerts} clipPolys={clippedRegion.Count}");
Console.WriteLine($"[pv-dump] local=[{string.Join(" ", System.Array.ConvertAll(poly, v => $"({v.X:F2},{v.Y:F2},{v.Z:F2})"))}]");
foreach (var cp in clippedRegion)
Console.WriteLine($"[pv-dump] clipped({cp.Vertices.Length})=[{string.Join(" ", System.Array.ConvertAll((Vector2[])cp.Vertices, v => $"({v.X:F3},{v.Y:F3})"))}]");
}
// Exit portal -> outdoors visible through this (clipped) opening.
// OutsideView gates DRAWN color (terrain/sky/scissor), and the
// shell that rasterizes this aperture draws +drawLiftZ above
@ -688,9 +640,6 @@ public static class PortalVisibilityBuilder
ProcessCellPortals(cell, 0);
}
if (pvDump)
Console.WriteLine($"[pv-dump] OUTSIDEVIEW polys={frame.OutsideView.Polygons.Count} bfsCellViews={frame.CellViews.Count} crossBldg={frame.CrossBuildingViews.Count}");
// Phase U.4c flap probe (ACDREAM_PROBE_FLAP) — read-only per-frame snapshot of the
// root cell's per-portal side-test + projection + the frame's exit/visible counts.
if (AcDream.Core.Rendering.RenderingDiagnostics.ProbeFlapEnabled)

View file

@ -42,14 +42,16 @@ public sealed record RuntimeOptions(
string? LivePass,
bool DevTools,
bool UncappedRendering,
/// <summary>#435 kept deliberately: NOT a spent probe. The canonical
/// nine-stop soak (`tools/run-connected-r6-soak.ps1`) hard-gates on the
/// `move-truth OUT` records this emits — it is the automated proof that
/// production input produced outbound movement traffic.</summary>
bool DumpMoveTruth,
bool DumpSky,
bool NoAudio,
int HidePartIndex,
bool RetailCloseDegrades,
bool DumpSceneryZ,
bool DumpLiveSpawns,
bool DumpClothing,
int? LegacyStreamRadius,
bool RetailUi,
/// <summary>Campaign CC slice CC4: interim env/test-only seam that opens
@ -157,8 +159,6 @@ public sealed record RuntimeOptions(
// only for before/after diagnostic comparisons.
RetailCloseDegrades: !string.Equals(env("ACDREAM_RETAIL_CLOSE_DEGRADES"), "0", StringComparison.Ordinal),
DumpSceneryZ: IsExactlyOne(env("ACDREAM_DUMP_SCENERY_Z")),
DumpLiveSpawns: IsExactlyOne(env("ACDREAM_DUMP_LIVE_SPAWNS")),
DumpClothing: IsExactlyOne(env("ACDREAM_DUMP_CLOTHING")),
// Legacy override for ACDREAM_STREAM_RADIUS. Caller applies it on
// top of the quality preset's radii. Null when unset or invalid.
LegacyStreamRadius: TryParseNonNegativeInt(env("ACDREAM_STREAM_RADIUS")),

View file

@ -525,11 +525,6 @@ public sealed class ItemInteractionController : IDisposable
switch (mode)
{
case InteractionModeKind.Use:
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] route=target-mode-click OfferPrimaryClick(Use) guid=0x{targetGuid:X8}");
}
ClearTargetMode();
accepted = ActivateItem(targetGuid);
break;
@ -562,11 +557,6 @@ public sealed class ItemInteractionController : IDisposable
/// </summary>
public bool UseSelectedOrEnterMode(uint selectedObjectId)
{
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] route=toolbar-or-queued-use UseSelectedOrEnterMode guid=0x{selectedObjectId:X8}");
}
if (selectedObjectId != 0)
return ActivateItem(selectedObjectId);
return _interactionState.EnterUse();
@ -666,11 +656,6 @@ public sealed class ItemInteractionController : IDisposable
public bool ActivateItem(uint itemGuid)
{
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] entry:ActivateItem guid=0x{itemGuid:X8} isTargetModeActive={IsTargetModeActive}");
}
if (itemGuid == 0) return false;
if (IsTargetModeActive)
@ -997,11 +982,6 @@ public sealed class ItemInteractionController : IDisposable
/// </summary>
public bool ExecuteConfirmedUse(uint objectId)
{
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] route=confirmed-use ExecuteConfirmedUse guid=0x{objectId:X8}");
}
if (objectId == 0u || (_requestUse is null && _sendUse is null))
return false;
if (!EnsureInventoryRequestReady())

View file

@ -377,13 +377,6 @@ public sealed class SelectedObjectController : IRetainedPanelController
? $"{stackSize} {objectName}"
: objectName;
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] ApplySelection guid=0x{g:X8} stackSizeOperand={stackSize} "
+ $"objectName={objectName ?? "null"} builtLabel={_currentName ?? "null"}");
}
// ── 3. Selection overlay: brief flash (retail container ObjectSelected
// = Pause(0.25s)→Normal). "StackedItemSelected" for stacks. ──────────────
SetOverlayState(stackSize > 1u
@ -410,18 +403,6 @@ public sealed class SelectedObjectController : IRetainedPanelController
_splitQuantity.Reset(stackSize, initialValue: seed);
if (_stackSizeEntry is not null) _stackSizeEntry.Visible = true;
if (_stackSizeSlider is not null) _stackSizeSlider.Visible = true;
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] ApplySelection guid=0x{g:X8} sliderVisible=true "
+ $"isVendorSplitExempt={vendorSplitExempt} maxSplitSize={stackSize} seed={seed}");
}
}
else if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] ApplySelection guid=0x{g:X8} sliderVisible=false "
+ $"failingPredicate=stackSize<=1u stackSize={stackSize}");
}
// ── 4. Health: query, and show the meter only if real health is already known.

View file

@ -21,15 +21,13 @@ internal sealed class LiveEntityDeletionController : ILiveEntityPruneSink
private readonly ILiveEntityTeardownCoordinator _teardown;
private readonly ILocalPlayerIdentitySource _identity;
private readonly DormantLiveEntityStore _dormant;
private readonly Action<string>? _diagnostic;
public LiveEntityDeletionController(
LiveEntityRuntime runtime,
RuntimeEntityObjectLifetime entityObjects,
ILiveEntityTeardownCoordinator teardown,
ILocalPlayerIdentitySource identity,
DormantLiveEntityStore? dormant = null,
Action<string>? diagnostic = null)
DormantLiveEntityStore? dormant = null)
{
_runtime = runtime ?? throw new ArgumentNullException(nameof(runtime));
_entityObjects = entityObjects
@ -37,7 +35,6 @@ internal sealed class LiveEntityDeletionController : ILiveEntityPruneSink
_teardown = teardown ?? throw new ArgumentNullException(nameof(teardown));
_identity = identity ?? throw new ArgumentNullException(nameof(identity));
_dormant = dormant ?? new DormantLiveEntityStore();
_diagnostic = diagnostic;
}
/// <summary>
@ -64,13 +61,6 @@ internal sealed class LiveEntityDeletionController : ILiveEntityPruneSink
if (removed)
{
_dormant.RemoveExact(delete);
_diagnostic?.Invoke(
$"live: delete guid=0x{delete.Guid:X8} instSeq={delete.InstanceSequence}");
}
else if (removedDormant)
{
_diagnostic?.Invoke(
$"live: delete dormant guid=0x{delete.Guid:X8} instSeq={delete.InstanceSequence}");
}
return removed || removedDormant;
}
@ -95,8 +85,6 @@ internal sealed class LiveEntityDeletionController : ILiveEntityPruneSink
return false;
_dormant.Retain(snapshot);
_diagnostic?.Invoke(
$"live: dormant guid=0x{candidate.ServerGuid:X8} instSeq={candidate.Generation}");
return true;
}
}

View file

@ -180,7 +180,6 @@ internal sealed class LiveEntityHydrationController : ILiveEntityLandblockLoaded
private readonly ILocalPlayerIdentitySource _identity;
private readonly LiveEntityDeletionController _deletion;
private readonly DormantLiveEntityStore _dormant;
private readonly Action<string>? _diagnostic;
/// <summary>
/// C3c: the graphical first-entry drive pump — pumped at the end of each
/// Create transaction so a fresh residence drives its conductor
@ -219,7 +218,6 @@ internal sealed class LiveEntityHydrationController : ILiveEntityLandblockLoaded
ILocalPlayerIdentitySource identity,
LiveEntityDeletionController deletion,
DormantLiveEntityStore? dormant = null,
Action<string>? diagnostic = null,
RuntimeFirstEntryDriveController? firstEntry = null,
RuntimeAcceptedPositionDriveController? acceptedPositionDrive = null)
{
@ -236,7 +234,6 @@ internal sealed class LiveEntityHydrationController : ILiveEntityLandblockLoaded
_identity = identity ?? throw new ArgumentNullException(nameof(identity));
_deletion = deletion ?? throw new ArgumentNullException(nameof(deletion));
_dormant = dormant ?? new DormantLiveEntityStore();
_diagnostic = diagnostic;
_firstEntry = firstEntry;
_acceptedPositionDrive = acceptedPositionDrive;
}
@ -465,11 +462,6 @@ AppearanceSynchronization:
ChildUnparentDisposition disposition =
_relationships.OnChildBecameUnparented(update.Guid);
bool accepted = disposition is not ChildUnparentDisposition.Superseded;
if (accepted)
{
_diagnostic?.Invoke(
$"live: pickup guid=0x{update.Guid:X8} instSeq={update.InstanceSequence} posSeq={update.PositionSequence}");
}
return accepted;
}
@ -601,7 +593,6 @@ AppearanceSynchronization:
if (candidates.Count == 0)
return;
int projected = 0;
lock (_datLock)
{
foreach (RuntimeEntityRecord candidate in candidates)
@ -623,26 +614,21 @@ AppearanceSynchronization:
candidate.Snapshot,
LiveProjectionPurpose.CreateSupersessionRecovery))
{
projected++;
projectedCanonicalAppearance = true;
}
}
else if (record?.WorldEntity is not null
&& record.InitialHydrationCompleted)
{
if (_runtime.RebucketLiveEntity(
record.ServerGuid,
record.ProjectionCellId))
{
projected++;
}
_runtime.RebucketLiveEntity(
record.ServerGuid,
record.ProjectionCellId);
}
else if (ProjectExact(
candidate,
candidate.Snapshot,
LiveProjectionPurpose.SpatialRecovery))
{
projected++;
projectedCanonicalAppearance = true;
}
@ -658,21 +644,14 @@ AppearanceSynchronization:
if (record is not null
&& _runtime.IsCurrentRecord(record)
&& record.AppearanceProjectionSynchronizationPending
&& SynchronizeAppearance(
record,
record.ObjDescAuthorityVersion))
&& record.AppearanceProjectionSynchronizationPending)
{
projected++;
SynchronizeAppearance(
record,
record.ObjDescAuthorityVersion);
}
}
}
if (projected > 0)
{
_diagnostic?.Invoke(
$"live: re-projected {projected} server object(s) into landblock 0x{loadedLandblockId:X8}");
}
}
public bool EnsureWorldOrigin(

View file

@ -822,13 +822,6 @@ public static class GameEventWiring
registrar.Register(GameEventType.ApproachVendor, e =>
{
var p = VendorApproach.TryParse(e.Payload.Span);
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] ApproachVendor(0x0062) inbound parsed={p is not null} "
+ $"vendorGuid={(p is null ? "n/a" : $"0x{p.Value.VendorGuid:X8}")} "
+ $"itemCount={(p is null ? "n/a" : p.Value.Items.Count.ToString())}");
}
if (p is null) return;
var profile = new VendorShopProfile(
@ -846,14 +839,6 @@ public static class GameEventWiring
for (int i = 0; i < shopItems.Length; i++)
{
VendorApproach.ItemProfile item = p.Value.Items[i];
if (VendorDiagnostics.DumpVendorEnabled && i < 5)
{
Console.WriteLine(
$"[vendor-diag] ApproachVendor wire-item[{i}] guid=0x{item.ItemGuid:X8} "
+ $"name={item.Desc.Name ?? "null"} "
+ $"descStackSize={(item.Desc.StackSize is { } ds ? ds.ToString() : "null")} "
+ $"stackSizeMax={(item.Desc.StackSizeMax is { } sm ? sm.ToString() : "null")}");
}
shopItems[i] = new VendorShopItem(
item.ItemGuid,
item.StackSize,
@ -950,12 +935,6 @@ public static class GameEventWiring
registrar.Register(GameEventType.UseDone, e =>
{
uint? err = GameEvents.ParseUseDone(e.Payload.Span);
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] UseDone(0x01C7) inbound parsed={err is not null} "
+ $"err={(err is null ? "n/a" : $"0x{err.Value:X4}")}");
}
if (err is null) return;
// Already the diagnostics-only log line SHOULD-FIX 4 asks for —
// it fires unconditionally, so an unmapped code below stays
@ -1038,12 +1017,9 @@ public static class GameEventWiring
// player this is the authoritative source (the per-item
// SpellBook flag in IdentifyObjectResponse is for caster
// items / scrolls only).
bool dumpPd = Environment.GetEnvironmentVariable("ACDREAM_DUMP_VITALS") == "1";
registrar.Register(GameEventType.PlayerDescription, e =>
{
var p = PlayerDescriptionParser.TryParse(e.Payload.Span);
if (dumpPd)
Console.WriteLine($"vitals: PlayerDescription body.len={e.Payload.Length} parsed={(p is null ? "NULL" : $"vec={p.Value.VectorFlags} attrs={p.Value.Attributes.Count} spells={p.Value.Spells.Count}")}");
if (p is null) return;
// R3: a trailer-truncated parse carries zero placeholder option
@ -1106,8 +1082,6 @@ public static class GameEventWiring
if (attr.Current is uint cur)
{
// Vital entry (id 7/8/9) — has absolute current.
if (dumpPd)
Console.WriteLine($"vitals: PD-vital id={attr.AtType} ranks={attr.Ranks} start={attr.Start} cur={cur}");
localPlayer.OnVitalUpdate(
vitalId: attr.AtType,
ranks: attr.Ranks,
@ -1120,8 +1094,6 @@ public static class GameEventWiring
// Primary attribute (id 1..6) — Endurance+Self feed
// the vital max formula (Endurance/2 for Health,
// Endurance for Stamina, Self for Mana).
if (dumpPd)
Console.WriteLine($"vitals: PD-attr id={attr.AtType} ranks={attr.Ranks} start={attr.Start}");
localPlayer.OnAttributeUpdate(
atType: attr.AtType,
ranks: attr.Ranks,
@ -1174,10 +1146,6 @@ public static class GameEventWiring
int total = (int)(formulaBonus + s.Init + s.Ranks);
if (s.SkillId == 24u) runSkill = total;
else if (s.SkillId == 22u) jumpSkill = total;
if (dumpPd)
Console.WriteLine(
$"vitals: PD-skill id={s.SkillId} init={s.Init} ranks={s.Ranks} formulaBonus={formulaBonus} total={total}");
}
if (runSkill >= 0 || jumpSkill >= 0)
onSkillsUpdated?.Invoke(runSkill, jumpSkill);

View file

@ -447,7 +447,7 @@ public static class PlayerDescriptionParser
}
}
}
catch (FormatException ex)
catch (FormatException)
{
// Trailer corrupted — keep what we have and flag it. Once
// Tasks 3-9 add list reads inside this try block, partial
@ -455,8 +455,6 @@ public static class PlayerDescriptionParser
// them so they can ignore the trailer if they need all-or-
// nothing semantics.
trailerTruncated = true;
if (System.Environment.GetEnvironmentVariable("ACDREAM_DUMP_VITALS") == "1")
System.Console.WriteLine($"PlayerDescriptionParser: trailer FormatException at pos={pos}/{payload.Length}: {ex.Message}");
}
return new Parsed(
@ -466,12 +464,9 @@ public static class PlayerDescriptionParser
shortcuts, hotbarSpells, desiredComps, spellbookFilters,
gameplayOptions, inventory, equipped, trailerTruncated);
}
catch (FormatException ex)
catch (FormatException)
{
// Truncation mid-walk — return null so caller knows parse failed.
// Diagnostic when ACDREAM_DUMP_VITALS=1 surfaces the failure point.
if (System.Environment.GetEnvironmentVariable("ACDREAM_DUMP_VITALS") == "1")
System.Console.WriteLine($"PlayerDescriptionParser: FormatException at pos={pos}/{payload.Length}: {ex.Message}");
return null;
}
}

View file

@ -780,15 +780,12 @@ public sealed class WorldSession : IDisposable
// Issue #5 diagnostics (env-var-gated):
// ACDREAM_DUMP_OPCODES=1 → log first occurrence of each unhandled opcode
// ACDREAM_DUMP_VITALS=1 → log every PrivateUpdateVital(Current) parse
// ACDREAM_DUMP_APPEARANCE=1 → log every 0xF625 ObjDescEvent + 0xF7DB UpdateObject
// with body len, target guid, hex preview. Used to
// debug remote-player appearance asymmetry (retail
// observer in acdream renders wrong skin/hair).
private static readonly bool DumpOpcodesEnabled =
Environment.GetEnvironmentVariable("ACDREAM_DUMP_OPCODES") == "1";
private static readonly bool DumpVitalsEnabled =
Environment.GetEnvironmentVariable("ACDREAM_DUMP_VITALS") == "1";
private static readonly bool DumpAppearanceEnabled =
Environment.GetEnvironmentVariable("ACDREAM_DUMP_APPEARANCE") == "1";
private readonly System.Collections.Generic.HashSet<uint> _seenUnhandledOpcodes = new();
@ -2249,8 +2246,6 @@ public sealed class WorldSession : IDisposable
// format per holtburger UpdateVital<false> — see
// PrivateUpdateVital.TryParseFull.
var parsed = PrivateUpdateVital.TryParseFull(body);
if (DumpVitalsEnabled)
Console.WriteLine($"vitals: 0x02E7 PrivateUpdateVital body.len={body.Length} parsed={(parsed is null ? "null" : $"v{parsed.Value.VitalId} ranks={parsed.Value.Ranks} start={parsed.Value.Start} cur={parsed.Value.Current}")}");
if (parsed is not null)
VitalUpdated?.Invoke(parsed.Value);
}
@ -2259,8 +2254,6 @@ public sealed class WorldSession : IDisposable
// Issue #5: current-only delta (regen ticks / drains).
// Wire format per holtburger UpdateVitalCurrent<false>.
var parsed = PrivateUpdateVital.TryParseCurrent(body);
if (DumpVitalsEnabled)
Console.WriteLine($"vitals: 0x02E9 PrivateUpdateVitalCurrent body.len={body.Length} parsed={(parsed is null ? "null" : $"v{parsed.Value.VitalId} cur={parsed.Value.Current}")}");
if (parsed is not null)
VitalCurrentUpdated?.Invoke(parsed.Value);
}

View file

@ -1,27 +0,0 @@
using System;
namespace AcDream.Core.Items;
/// <summary>
/// TEMPORARY diagnostic-probe owner for two live-only regressions that have
/// each survived two green-tested fixes: Chain A (a far-click walk-to-use
/// approaches a vendor, the vendor plays its cosmetic greeting, but the shop
/// window never opens) and Chain B (selecting a splittable vendor stack
/// shows the bare item name with no quantity slider). Every probe line is
/// prefixed <c>[vendor-diag]</c> and gated on <see cref="DumpVendorEnabled"/>
/// so the family is a true no-op when the flag is unset.
/// </summary>
/// <remarks>
/// Read once from <c>ACDREAM_DUMP_VENDOR=1</c> at process start, per Code
/// Structure Rule 5 (one static diagnostic-owner class per subsystem, no
/// per-call-site <see cref="Environment.GetEnvironmentVariable"/> reads).
/// Lives in <c>AcDream.Core</c> — the one project every call site (App,
/// Core.Net, Runtime) already references — so a single flag instance is
/// shared across the whole probe family regardless of which layer observes
/// it first.
/// </remarks>
public static class VendorDiagnostics
{
public static bool DumpVendorEnabled { get; } =
Environment.GetEnvironmentVariable("ACDREAM_DUMP_VENDOR") == "1";
}

View file

@ -1637,7 +1637,7 @@ public static class PhysicsDiagnostics
// channel), naming which phase halted the attempt and, on Collided,
// the colliding polygon's normal and which of the three channels
// wrote it.
// [transit-fail-stepup] — DoStepUp entry/exit, mirroring the existing
// [transit-fail-stepup] — DoStepUp entry/exit, mirroring the retired
// ACDREAM_DUMP_STEPUP probe's own input-normal-and-verdict content
// so a stuck-tick capture carries the step chain without running a
// second flag.
@ -1753,7 +1753,7 @@ public static class PhysicsDiagnostics
/// <summary>
/// One line per <c>Transition.DoStepUp</c> entry or exit, mirroring the
/// content of the existing <c>ACDREAM_DUMP_STEPUP</c> probe (same input
/// content of the retired <c>ACDREAM_DUMP_STEPUP</c> probe (same input
/// normal / walkable verdict / landing-plane fields) so a stuck-tick
/// capture carries the step-up chain without a second flag.
/// <paramref name="edge"/> is <c>"enter"</c> or <c>"exit"</c>;

View file

@ -1349,9 +1349,6 @@ public sealed class Transition
CollisionInfo.CopyFrom(source.CollisionInfo);
}
private static bool DumpEdgeSlideEnabled =>
Environment.GetEnvironmentVariable("ACDREAM_DUMP_EDGE_SLIDE") == "1";
// -----------------------------------------------------------------------
// A6.P7 (2026-05-25) — retail-binary shape dispatch rule
// -----------------------------------------------------------------------
@ -2227,7 +2224,6 @@ public sealed class Transition
if (ci.ContactPlaneValid)
return TransitionState.OK;
DumpStepDownBranchGate(contactInvalid: true);
if (oi.Contact && !sp.StepDown && sp.CheckCellId != 0 && oi.StepDown)
{
// L.2.3i (2026-04-29): retail uses FloorZ when OnWalkable,
@ -2280,7 +2276,6 @@ public sealed class Transition
// intentionally narrow: it tells the next L.2c slice whether
// we are missing precipice context, a steep contact plane, or
// merely the EdgeSlide flag.
DumpEdgeSlideStepDownFailed(stepDownHeight, zVal);
bool stop = EdgeSlideAfterStepDownFailed(
engine,
@ -2469,7 +2464,6 @@ public sealed class Transition
TransitionCellCollisionPhase.Objects,
cellId,
FindObjCollisionsInCell(engine, cellId));
DumpPhase2(innerAttempt, environment, objects);
PhysicsDiagnostics.TraceTransitInsertAttempt(
ObjectInfo.SelfEntityId, innerAttempt, "objects",
environment, building, objects, objects,
@ -2501,7 +2495,6 @@ public sealed class Transition
// No steep-plane exception precedes this gate (0050b3d8-0050b3e7).
if (!oi.OnWalkable || !oi.EdgeSlide)
{
DumpEdgeSlideBranch("branch1/!onwalkable-or-!edgeslide", zVal);
sp.ClearWalkable();
sp.RestoreCheckPos();
ci.ContactPlaneValid = false;
@ -2513,7 +2506,6 @@ public sealed class Transition
if (ci.ContactPlaneValid && ci.ContactPlane.Normal.Z < zVal)
{
var cliffPlane = ci.ContactPlane;
DumpEdgeSlideBranch("branch2/steep-cliffslide", zVal);
sp.ClearWalkable();
sp.RestoreCheckPos();
ci.ContactPlaneValid = false;
@ -2536,7 +2528,6 @@ public sealed class Transition
// rapidly down the stairs. Do not restore stale history here.
if (sp.HasWalkablePolygon)
{
DumpEdgeSlideBranch("branch3/precipice-slide", zVal);
sp.RestoreCheckPos();
ci.ContactPlaneValid = false;
ci.ContactPlaneIsWater = false;
@ -2546,7 +2537,6 @@ public sealed class Transition
if (ci.ContactPlaneValid)
{
DumpEdgeSlideBranch("branch4/contact-no-walkable", zVal);
sp.ClearWalkable();
sp.RestoreCheckPos();
ci.ContactPlaneValid = false;
@ -2624,8 +2614,6 @@ public sealed class Transition
Vector3 collideNormal = new(-contactNormal.Y, contactNormal.X, 0f);
if (collideNormal.LengthSquared() < PhysicsGlobals.EpsilonSq)
{
DumpCliffSlide("degenerate-cross/last-known", contactPlane,
new Plane(referenceNormal, 0f), contactNormal, 0f, false);
return TransitionState.OK;
}
@ -2633,8 +2621,6 @@ public sealed class Transition
Vector3 offset = sp.GlobalSphere[0].Origin - sp.GlobalCurrCenter[0].Origin;
float angle = Vector3.Dot(collideNormal, offset);
DumpCliffSlide("ok/last-known", contactPlane,
new Plane(referenceNormal, 0f), collideNormal, angle, true);
if (angle <= 0f)
{
@ -2650,89 +2636,6 @@ public sealed class Transition
return TransitionState.Adjusted;
}
private void DumpEdgeSlideStepDownFailed(float stepDownHeight, float zVal)
{
if (!DumpEdgeSlideEnabled) return;
var sp = SpherePath;
var ci = CollisionInfo;
var oi = ObjectInfo;
Console.WriteLine(
System.FormattableString.Invariant(
$"edge-slide: stepdown-failed cur={Fmt(sp.CurPos)} check={Fmt(sp.CheckPos)} cell=0x{sp.CheckCellId:X8} edgeFlag={oi.EdgeSlide} contactFlag={oi.Contact} onWalkable={oi.OnWalkable} contactPlane={ci.ContactPlaneValid} lastPlane={ci.LastKnownContactPlaneValid} walkableValid={sp.WalkableValid} walkablePoly={sp.HasWalkablePolygon} lastWalkablePoly={sp.HasLastWalkablePolygon} stepDown={stepDownHeight:F3} zVal={zVal:F3}"));
}
/// <summary>
/// L.4-diag: log step-down branch gate decision. Whether we entered or
/// skipped the contact-recovery branch matters for whether CliffSlide
/// has any chance of firing.
/// </summary>
private void DumpStepDownBranchGate(bool contactInvalid)
{
if (!DumpEdgeSlideEnabled) return;
var sp = SpherePath;
var ci = CollisionInfo;
var oi = ObjectInfo;
bool wouldEnter = contactInvalid && oi.Contact && !sp.StepDown
&& sp.CheckCellId != 0 && oi.StepDown;
if (!wouldEnter) return; // only log when entering, to keep noise low
Console.WriteLine(
System.FormattableString.Invariant(
$"edge-slide: stepdown-branch-enter cur={Fmt(sp.CurPos)} contactValid={ci.ContactPlaneValid} contactN.Z={(ci.ContactPlaneValid ? ci.ContactPlane.Normal.Z : 0f):F3} onWalk={oi.OnWalkable} contact={oi.Contact}"));
}
/// <summary>
/// L.4-diag: log Phase 2 outcome per inner attempt. Tells us whether
/// we're churning in Slid retries or escaping to step-down branch.
/// </summary>
private void DumpPhase2(int attempt, TransitionState envState, TransitionState objState)
{
if (!DumpEdgeSlideEnabled) return;
if (objState == TransitionState.OK) return; // skip clean attempts
Console.WriteLine(
System.FormattableString.Invariant(
$"edge-slide: phase2 attempt={attempt} env={envState} obj={objState}"));
}
/// <summary>
/// L.4-diag: log which branch of EdgeSlideAfterStepDownFailed fired.
/// Tells us whether CliffSlide gets called or whether we hit a
/// stop-at-edge branch.
/// </summary>
private void DumpEdgeSlideBranch(string branch, float zVal)
{
if (!DumpEdgeSlideEnabled) return;
var sp = SpherePath;
var ci = CollisionInfo;
var oi = ObjectInfo;
Console.WriteLine(
System.FormattableString.Invariant(
$"edge-slide: branch={branch} contactValid={ci.ContactPlaneValid} contactN.Z={(ci.ContactPlaneValid ? ci.ContactPlane.Normal.Z : 0f):F3} lastValid={ci.LastKnownContactPlaneValid} lastN.Z={(ci.LastKnownContactPlaneValid ? ci.LastKnownContactPlane.Normal.Z : 0f):F3} walkPolyValid={sp.HasWalkablePolygon} walkPolyN.Z={(sp.HasWalkablePolygon ? sp.WalkablePlane.Normal.Z : 0f):F3} lastWalkPolyN.Z={(sp.HasLastWalkablePolygon ? sp.LastWalkablePlane.Normal.Z : 0f):F3} onWalk={oi.OnWalkable} edgeFlag={oi.EdgeSlide} zVal={zVal:F3}"));
}
/// <summary>
/// L.4-diag: log CliffSlide invocation. Tells us whether the
/// cross-product is degenerate (no slide) or producing a real
/// deflection.
/// </summary>
private void DumpCliffSlide(string outcome, Plane current, Plane lastKnown,
Vector3 collideNormal, float angle, bool willApply)
{
if (!DumpEdgeSlideEnabled) return;
Console.WriteLine(
System.FormattableString.Invariant(
$"edge-slide: cliffslide outcome={outcome} curN={Fmt(current.Normal)} lastN={Fmt(lastKnown.Normal)} collideN={Fmt(collideNormal)} angle={angle:F4} apply={willApply}"));
}
private static string Fmt(Vector3 value) =>
System.FormattableString.Invariant($"({value.X:F3},{value.Y:F3},{value.Z:F3})");
// -----------------------------------------------------------------------
// Environment collision — outdoor terrain
// -----------------------------------------------------------------------
@ -5739,29 +5642,9 @@ public sealed class Transition
var ci = CollisionInfo;
var oi = ObjectInfo;
// L.2.3f (2026-04-29): diagnostic for steep-roof bug. Logs the
// input polygon normal that triggered step-up. The verdict tells
// whether THIS polygon would pass FloorZ (≈ 0.66) — but actual
// step-up acceptance depends on the polygon found by step_sphere_down
// INSIDE the recursive TransitionalInsert, which may be different.
// The post-step "result=" line below logs that outcome.
bool diag = Environment.GetEnvironmentVariable("ACDREAM_DUMP_STEPUP") == "1";
if (diag)
{
float floor = PhysicsGlobals.FloorZ;
string verdict = collisionNormal.Z >= floor ? "WALKABLE" : "STEEP";
Console.WriteLine(
$"stepup: enter normal=({collisionNormal.X:F3},{collisionNormal.Y:F3},{collisionNormal.Z:F3}) " +
$"|Z|={collisionNormal.Z:F3} vs FloorZ={floor:F3} → {verdict}, " +
$"OnWalkable={(oi.State & ObjectInfoState.OnWalkable) != 0}, " +
$"StepUpHeight={oi.StepUpHeight:F3}, " +
$"CurPos=({sp.CurPos.X:F2},{sp.CurPos.Y:F2},{sp.CurPos.Z:F2})");
}
// #345 probe (2026-08-08): mirrors the ACDREAM_DUMP_STEPUP content
// above into the buffered stuck-tick trace (self-guards internally,
// zero cost when ACDREAM_DUMP_TRANSIT_FAIL is unset) so a stuck-tick
// capture carries the step-up chain without a second flag.
// #345 probe (2026-08-08): buffers this step-up attempt into the
// stuck-tick trace (self-guards internally, zero cost when
// ACDREAM_DUMP_TRANSIT_FAIL is unset).
PhysicsDiagnostics.TraceTransitStepUp(
oi.SelfEntityId, "enter", collisionNormal,
onWalkable: (oi.State & ObjectInfoState.OnWalkable) != 0,
@ -5807,28 +5690,6 @@ public sealed class Transition
sp.StepUp = false;
sp.ClearWalkable();
// L.2.3f: log the result + landing plane if step-up succeeded.
// This is the actual surface the player ended up on, which may
// differ from the input collision normal (e.g. step-up scanned
// past a steep slope and landed on a flatter polygon higher up).
if (diag)
{
if (stepDown && ci.ContactPlaneValid)
{
float floor = PhysicsGlobals.FloorZ;
string verdict = ci.ContactPlane.Normal.Z >= floor ? "WALKABLE" : "STEEP";
Console.WriteLine(
$"stepup: SUCCESS — landed on plane normal=" +
$"({ci.ContactPlane.Normal.X:F3},{ci.ContactPlane.Normal.Y:F3},{ci.ContactPlane.Normal.Z:F3}) " +
$"|Z|={ci.ContactPlane.Normal.Z:F3} vs FloorZ={floor:F3} → {verdict}, " +
$"new CheckPos=({sp.CheckPos.X:F2},{sp.CheckPos.Y:F2},{sp.CheckPos.Z:F2})");
}
else
{
Console.WriteLine($"stepup: FAILED — sliding back along normal");
}
}
// #345 probe (2026-08-08): the matching exit line for the "enter"
// trace above.
PhysicsDiagnostics.TraceTransitStepUp(

View file

@ -224,11 +224,6 @@ public sealed class RuntimeInteractionTransactionState : IDisposable
verdict = RuntimeInteractionDispatchResult.Dispatched;
}
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] TryDispatchUse guid=0x{serverGuid:X8} ownedByPlayer={ownedByPlayer} useable={useable} verdict={verdict} seq={sequence}");
}
return verdict;
}
@ -633,11 +628,6 @@ public sealed class RuntimeInteractionTransactionState : IDisposable
if (_pendingUse is not { } current
|| current.ApproachToken != approachToken)
{
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] TryResolveUseApproachCompletion no-match approachToken=({approachToken.ControllerLifetime},{approachToken.ApproachGeneration}) natural={natural} hasPendingUse={_pendingUse is not null}");
}
pending = default;
return false;
}
@ -645,11 +635,6 @@ public sealed class RuntimeInteractionTransactionState : IDisposable
_pendingUse = null;
pending = current;
IncrementRevision();
if (VendorDiagnostics.DumpVendorEnabled)
{
Console.WriteLine(
$"[vendor-diag] TryResolveUseApproachCompletion guid=0x{pending.ServerGuid:X8} natural={natural} accepted={natural}");
}
return natural;
}

View file

@ -191,7 +191,6 @@ public sealed class VendorShopItemMaterializer : IDisposable
}
}
int diagIndex = 0;
foreach (VendorShopItem item in currentItems)
{
bool ownedAlready = _ownedGuids.ContainsKey(item.ItemGuid);
@ -208,16 +207,6 @@ public sealed class VendorShopItemMaterializer : IDisposable
}
WeenieData materialized = ToWeenieData(item, transition.VendorId);
if (VendorDiagnostics.DumpVendorEnabled && diagIndex < 5)
{
Console.WriteLine(
$"[vendor-diag] materialize[{diagIndex}] guid=0x{item.ItemGuid:X8} "
+ $"descStackSize={(item.DescStackSize is { } ds ? ds.ToString() : "null")} "
+ $"maxStackSize={(item.MaxStackSize is { } ms ? ms.ToString() : "null")} "
+ $"resolvedStackSize={(materialized.StackSize is { } rs ? rs.ToString() : "null")} "
+ $"resolvedStackSizeMax={(materialized.StackSizeMax is { } rm ? rm.ToString() : "null")}");
diagIndex++;
}
_objects.Ingest(materialized);
nextOwned[item.ItemGuid] = transition.VendorId;