From eda8278a64d6d0924d9c1d88acd52aa6c39d97b7 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 14 May 2026 17:59:57 +0200 Subject: [PATCH] feat(B.6 slice 1): ACDREAM_PROBE_AUTOWALK diagnostic baseline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per the B.6 design spec (now retail-grounded on Option A), slice 1 is pure-additive logging so the next session has a clean trace of what ACE actually sends to the local player during a server-initiated auto-walk. New PhysicsDiagnostics.ProbeAutoWalkEnabled static flag, env-var- initialized from ACDREAM_PROBE_AUTOWALK=1. Probe sites: [autowalk-out] on SendUse + SendPickUp — the packets that trigger ACE's CreateMoveToChain when the target is out of WithinUseRadius. [autowalk-mt] on OnLiveMotionUpdated for _playerServerGuid only — captures MovementType + MoveToPath origin/min-dist/obj-dist + moveTowards + speed/runRate. Lets us see exactly the wire data retail's PerformMovement case 6 (0x00524440) was acting on. [autowalk-up] on OnLivePositionUpdated for _playerServerGuid only — cadence + payload of ACE's position broadcasts during auto-walk. No behavior change. All flags off by default; opt in with the env var during a focused reproduction. Designed to be mirrored into DebugVM checkbox state later (parallel to ProbeResolve / ProbeCell / ProbeBuilding) but not wired yet — env-var-only for the first trace session. --- src/AcDream.App/Rendering/GameWindow.cs | 51 +++++++++++++++++++ .../Physics/PhysicsDiagnostics.cs | 26 ++++++++++ 2 files changed, 77 insertions(+) diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 12b1c6c..f25f58b 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -3290,6 +3290,29 @@ public sealed class GameWindow : IDisposable { // Still update the stance echo (_playerMotionTableId, etc) via // the paths above, but don't stomp the animation sequencer. + + // B.6 slice 1 (2026-05-14): trace inbound motion for the + // local player so we can characterize what ACE sends during + // a server-initiated auto-walk. One line per inbound UM, + // gated on ACDREAM_PROBE_AUTOWALK=1. + if (AcDream.Core.Physics.PhysicsDiagnostics.ProbeAutoWalkEnabled) + { + string cmdHex = command.HasValue ? $"0x{command.Value:X4}" : "null"; + string pathStr = update.MotionState.MoveToPath is { } p + ? $"path=cell=0x{p.OriginCellId:X8},xyz=({p.OriginX:F2},{p.OriginY:F2},{p.OriginZ:F2}),minDist={p.MinDistance:F2},objDist={p.DistanceToObject:F2}" + : "path=null"; + string spd = update.MotionState.ForwardSpeed is { } fs + ? $"fwdSpd={fs:F2}" + : "fwdSpd=null"; + string mtsSpd = update.MotionState.MoveToSpeed is { } ms + ? $"mtSpd={ms:F2}" + : "mtSpd=null"; + string mtsRun = update.MotionState.MoveToRunRate is { } mr + ? $"mtRun={mr:F2}" + : "mtRun=null"; + Console.WriteLine(System.FormattableString.Invariant( + $"[autowalk-mt] stance=0x{stance:X4} cmd={cmdHex} mt=0x{update.MotionState.MovementType:X2} isMoveTo={update.MotionState.IsServerControlledMoveTo} moveTowards={update.MotionState.MoveTowards} {pathStr} {spd} {mtsSpd} {mtsRun}")); + } } else { @@ -4149,6 +4172,22 @@ public sealed class GameWindow : IDisposable (lbY - _liveCenterY) * 192f, 0f); var worldPos = new System.Numerics.Vector3(p.PositionX, p.PositionY, p.PositionZ) + origin; + + // B.6 slice 1 (2026-05-14): trace inbound UpdatePosition cadence for + // the local player. Combined with [autowalk-mt] this answers + // whether ACE's broadcast frequency during a server-initiated + // auto-walk is dense enough to drive smooth visible motion (the + // Option C viability check from the design spec). Gated on + // ACDREAM_PROBE_AUTOWALK=1; skips remote entities. + if (update.Guid == _playerServerGuid + && AcDream.Core.Physics.PhysicsDiagnostics.ProbeAutoWalkEnabled) + { + string velStr = update.Velocity is { } v + ? $"vel=({v.X:F2},{v.Y:F2},{v.Z:F2})" + : "vel=null"; + Console.WriteLine(System.FormattableString.Invariant( + $"[autowalk-up] cell=0x{p.LandblockId:X8} pos=({p.PositionX:F2},{p.PositionY:F2},{p.PositionZ:F2}) world=({worldPos.X:F2},{worldPos.Y:F2},{worldPos.Z:F2}) {velStr} grounded={update.IsGrounded}")); + } var rot = new System.Numerics.Quaternion(p.RotationX, p.RotationY, p.RotationZ, p.RotationW); DumpMovementTruthServerEcho(update, worldPos); @@ -8896,6 +8935,12 @@ public sealed class GameWindow : IDisposable var body = AcDream.Core.Net.Messages.InteractRequests.BuildUse(seq, guid); _liveSession.SendGameAction(body); Console.WriteLine($"[B.4b] use guid=0x{guid:X8} seq={seq}"); + if (AcDream.Core.Physics.PhysicsDiagnostics.ProbeAutoWalkEnabled) + { + string label = DescribeLiveEntity(guid); + Console.WriteLine(System.FormattableString.Invariant( + $"[autowalk-out] op=use target=0x{guid:X8} name=\"{label}\" seq={seq}")); + } } private void SendPickUp(uint itemGuid) @@ -8925,6 +8970,12 @@ public sealed class GameWindow : IDisposable seq, itemGuid, _playerServerGuid, placement: 0); _liveSession.SendGameAction(body); Console.WriteLine($"[B.5] pickup item=0x{itemGuid:X8} container=0x{_playerServerGuid:X8} seq={seq}"); + if (AcDream.Core.Physics.PhysicsDiagnostics.ProbeAutoWalkEnabled) + { + string label = DescribeLiveEntity(itemGuid); + Console.WriteLine(System.FormattableString.Invariant( + $"[autowalk-out] op=pickup target=0x{itemGuid:X8} name=\"{label}\" seq={seq}")); + } } private uint? SelectClosestCombatTarget(bool showToast) diff --git a/src/AcDream.Core/Physics/PhysicsDiagnostics.cs b/src/AcDream.Core/Physics/PhysicsDiagnostics.cs index f30a741..95cd927 100644 --- a/src/AcDream.Core/Physics/PhysicsDiagnostics.cs +++ b/src/AcDream.Core/Physics/PhysicsDiagnostics.cs @@ -94,4 +94,30 @@ public static class PhysicsDiagnostics /// /// public static ResolvedPolygon? LastBspHitPoly { get; set; } + + /// + /// B.6 slice 1 (2026-05-14) — baseline trace for the local-player + /// server-initiated auto-walk path (issue #63). When true, the + /// following events emit one-line [autowalk-*] logs: + /// + /// [autowalk-out] on every SendUse + /// / SendPickUp the local player issues — these are the + /// packets that may trigger ACE's server-side CreateMoveToChain + /// when the target is out of WithinUseRadius. + /// [autowalk-mt] on every inbound + /// UpdateMotion for the local player — captures the + /// MovementType + MoveToPath + speed/runRate ACE sends. + /// [autowalk-up] on every inbound + /// UpdatePosition for the local player — answers "what's + /// ACE's broadcast cadence during auto-walk?" + /// + /// Initial state from ACDREAM_PROBE_AUTOWALK=1. + /// + /// + /// Spec: docs/superpowers/specs/2026-05-14-phase-b6-design.md + /// §"Required investigation". + /// + /// + public static bool ProbeAutoWalkEnabled { get; set; } = + Environment.GetEnvironmentVariable("ACDREAM_PROBE_AUTOWALK") == "1"; }