docs #174: root mechanism found — player motion-queue backlog starves movetos

Probe round (ACDREAM_PROBE_AUTOWALK) discriminated the candidates: the
local player's pending-motion queue drains at ~1 node/sec and backs up
minutes deep during active play (last pending=False at the first
MovementJump press; old jump motions still completing at rest minutes
later). MotionsPending() then starves BeginTurnToHeading/
BeginMoveForward (verbatim retail gates): far-range Uses ARE sent and
ACE replies mt-6 walk-to-door but the body never walks; close-range
Uses park on a turn that never completes — both faces of "door does
not work", while a fresh session (shallow queue) works perfectly.
Retail's queue stays shallow (the #170 cdb drain trace: adds == dones)
— this is the #170 pending_motions family, local-player DRAIN-rate
edition. Fix path: decomp CheckForCompletedMotions (0x0051bfd0) pop
semantics + queue-dump probe first; no MotionsPending bypass, no
deferral-skipping band-aids.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-07-05 16:17:43 +02:00
parent 6811fc53d9
commit 62b6fa52e8

View file

@ -94,13 +94,44 @@ ACE's MoveToChain server-side — unproven, replies not captured).
`BeginTurnToHeading` gates). Captures in the session scratchpad
(`door-use3.pcapng`, `door-use4.pcapng`).
**Next:** relaunch with `ACDREAM_PROBE_AUTOWALK=1`; user clicks the door
(a) standing still, (b) right after moving. `[autowalk-end reason=complete
err=…]` vs silence discriminates cancel-vs-starved. Fix per retail: the use
flow must either complete the turn and fire, or surface the cancel
(retail re-queues/cancels visibly — decomp the client use flow §9a/§9b before
patching). DO NOT band-aid by skipping the deferral (the turn-to-face is
retail behavior).
**ROOT MECHANISM FOUND (2026-07-05 evening, probe round `launch-174-autowalk.log`):
the local player's pending-motion queue drains at ~1 node/sec and backs up
minutes deep during active play — MotionsPending() then starves every
manager-driven movement.** Chain, all evidence in the log:
1. Fresh session, standing at the door: every Use completes same-tick
(`[autowalk-end] err=None` ×6, seqs 1116 sent, door opens — "now it
works??"). Queue shallow ⇒ pipeline healthy.
2. After the jump/run sequence: the LAST player `pending=False` completion
is at the first `MovementJump Press` (log line 371); from there to the
end (line 939) every player MOTIONDONE reports `pending=True` — INCLUDING
at rest, with old jump-family motions (0x6500000D/0F) still completing
minutes later. That is a slow-draining BACKLOG, not one immortal node.
3. With MotionsPending() true, `BeginTurnToHeading`/`BeginMoveForward`
(retail 0x00529b90 `if (motions_pending) return`) never start:
- far range (wire-proven, seqs 98101): Use SENT, ACE replies mt-6
MoveToObject (objDist=0.50 — ACE is healthy), `[autowalk-begin]
mt=0x06` arms, body NEVER walks ([autowalk-up] position frozen) → ACE
waits forever → door never opens. Same as the original session's
642647.
- close range (round-3 silence): TurnToObject armed, never completes →
`_pendingPostArrivalAction` never fires → use eaten with zero feedback.
4. Retail contrast: the #170 live cdb drain trace showed retail's queue
stays SHALLOW (add_to_queue == MotionDone, drained same-tick); our
`CheckForCompletedMotions` completes ~one node per animation cycle, so
adds outpace drains during any active play. This is the #170
pending_motions-flood family — LOCAL-player drain-rate edition (the
remote fix `427332ac` removed the flood's feeder; the local queue's
DRAIN semantics are the divergence here).
**Next (fix session):** oracle-first on the drain: decomp
`MotionTableManager::CheckForCompletedMotions` (0x0051bfd0) +
`AnimationDone/MotionDone` pop semantics — which queued nodes retail
completes per tick (superseded/non-playing nodes must flush immediately,
not serialize behind animations). Add a queue-dump probe (node ids + ages)
before changing anything. Then re-verify the door BOTH branches + re-check
`UseDone` (0x01C7) wiring so ACE rejections become visible.
DO NOT band-aid: no MotionsPending bypass in BeginTurnToHeading (the gate
is verbatim retail), no deferral-skipping (turn-to-face is retail).
---