Fresh-session handoff for the INBOUND (remote-entity) motion arc. Captures the
symptom (walk<->run transition without stopping = interpreter reacts too slowly
-> animation+position desync compounding through turns; plus sliding + stop
position errors), the root-cause hypothesis (acdream lacks retail's CMotionInterp/
CSequence motion-transition state machine: pending_motions/MotionDone), the
pre-paid research (2026-06-04 sequencer deep-dive, 2026-06-26 audit D7-D12), the
decomp anchors, the inbound code map, the /investigate-then-port plan, the
live-capture setup, and the discipline reminders (report-only, surgical
sequencer integration, decomp-verbatim). Prior outbound/local arc shipped clean
through d34721fa.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
8.5 KiB
Handoff: inbound animation + position — verbatim retail port
Date: 2026-07-02
Branch: claude/vigorous-joliot-f0c3ad (clean; prior arc all committed through d34721fa)
Mode for the new session: /investigate first (report-only), then port on approval.
What just shipped (context — the OUTBOUND / LOCAL half is done)
This session made acdream's outbound wire and local-player motion retail-faithful, verified against live ACE + user/retail-observer sign-off:
- L.1b
2c8620ea— dualIMotionCommandCatalog(AceModern runtime / Retail2013 conformance, fullcommand_ids[0x198]extraction). - L.2b
78e163a4+ sign-offf271a49e— outbound wire parity (D1 default-differenceRawMotionState::Pack, D3 contact/longjump byte, D4JumpPack). - D6
4ed27836(pseudocode) +0f099bb6(D6.2a) +47407506(sign-off) +d34721fa(D6.2b) — portedCMotionInterp::adjust_motion/apply_run_to_command/apply_raw_movement/get_state_velocityand unified the local player's velocity + turn + jump + wire onto one input-builtRawMotionStateatforward_speed=1.0. Backward/strafe-left no longer zero; strafe retail-exact; turn omega from interpretedturn_speed. - Key wire finding: ACE recomputes the broadcast run speed from run
skill (echo-test confirmed) and auto-upgrades
WalkForward+HoldKey.Run → RunForward. The wire sends rawforward_speed=1.0. (Crib:claude-memory/project_retail_motion_outbound.md.)
That was OUTBOUND + LOCAL. This handoff is the INBOUND / REMOTE half.
The goal
Port retail's incoming (inbound) handling of animation + position VERBATIM into acdream — but surgically, targeted at where acdream deviates (not a blind wholesale sequencer rewrite; a rushed sequencer swap has "broken everything" in a past session — integrate carefully). Strict standard: no approximations; retail decomp / ACE / DAT as oracles; parity tests before behavior changes.
The symptom (the acceptance oracle — user's live observation)
Watching a remote player (inbound motion) in acdream:
- Overall "works OK" but not polished. Some sliding and some position errors once the entity stops.
- The worst offender: transitioning walk↔run WITHOUT stopping — the motion interpreter reacts too slowly, and this throws all animation + position off afterward, compounding as the entity keeps running around + turning. The error accumulates through subsequent motion.
Fixing the walk↔run-transition responsiveness (and the resulting animation + position desync) IS the acceptance test.
Root-cause hypothesis (UNCONFIRMED — verify in the investigation first)
acdream's motion sequencer does not implement retail's motion-transition
state machine. Retail's CMotionInterp doesn't just swap the animation cycle
on a motion change — it appends the new motion to a CSequence and
transitions through it with pending_motions / MotionDone bookkeeping. If
acdream applies a walk↔run change abruptly/late (snap SetCycle) instead of
sequencing it, the animation cycle and the dead-reckoned position drift apart
and the error accumulates. The 2026-06-04 deep-dive already ranked missing
pending_motions / MotionDone as HIGH.
Pre-paid research to leverage (READ THESE)
docs/research/2026-06-04-animation-sequencer-deep-dive.md— START HERE. RetailCMotionInterp+CSequence+ hook-dispatch state graph + 8 ranked divergences (missingpending_motions/MotionDoneHIGH; frame-swap class; link→cycle boundary). Verify its findings against the CURRENT code — the L.1 animation work may have closed some gaps since 2026-06-04; do not trust its line numbers.docs/research/2026-06-26-movement-animation-retail-parity-audit.md— the inbound divergences: D7 (animation split from retail motion flow), D8 (force-walk /MoveToManagerapproximate), D9 (inboundTurnToObject/TurnToHeadingtypes 8/9 dropped — CONFIRMED live:mt=0x09arrives and justSetCycle(Ready)instead of turning), D10 (spawn-time MoveTo weak), D11 (sequence/autonomy parsed then discarded), D12 (jump/contact gates simplified).docs/research/2026-07-01-d6-motion-interp-pseudocode.md— the OUTBOUND/localCMotionInterpport already done; inbound uses the SAME machinery (get_state_velocity,adjust_motion,apply_raw_movementnow exist insrc/AcDream.Core/Physics/MotionInterpreter.cs).
Decomp anchors (the oracle; grep docs/research/named-retail/acclient_2013_pseudo_c.txt)
CMotionInterp::apply_current_movement(~line 305713 — sequences style / forward-falling / sidestep / turn / actions),DoInterpretedMotion(~305575),CMotionTable::GetObjectSequence(~298636).CSequenceappend/advance/update (~lines 301622, 301777, 301839, 302425).- The 2026-06-04 deep-dive has the full CMotionInterp/CSequence address list.
acclient.hfor the structs; Ghidra HTTP bridge athttp://127.0.0.1:8081(decompile-by-address) if it's up.
Where the inbound code lives (starting points to map)
src/AcDream.App/Rendering/GameWindow.cs— inbound remote-entity motion:OnLiveMotionUpdated, the remoteSetCycle/ObservedOmegaseeding (~4815-4856), dead-reckoned position + omega application (~9750-9865), the[SETCYCLE]/[SCFAST]/[SCFULL]/[OMEGA_DIAG]/[VEL_DIAG]/[SEQSTATE]/[UPCYCLE]diagnostics.src/AcDream.Core/Physics/AnimationSequencer.cs— the cycle/action sequencer.src/AcDream.Core/Physics/MotionInterpreter.cs— interpreted state (now has the D6adjust_motion/apply_raw_movement/get_state_velocity).src/AcDream.Core/Physics/RemoteMoveToDriver.cs— remote MoveTo +TurnRateFor.src/AcDream.Core.Net/Messages/UpdateMotion.cs,UpdatePosition.cs,MoveToState.cs— inbound parsing.
The plan for the new session
- /investigate (report-only): produce a ranked deviation map —
where acdream's inbound animation + position handling deviates from retail's
CMotionInterp/CSequence, anchored on the walk↔run transition-lag symptom (not a whole-system rewrite). Parallel research agents are a good fit. Optionally corroborate with a live capture (below). Deliver the report- recommended verbatim-port slices; get explicit approval before edits.
- Port (after approval): verbatim-port the deviating retail mechanisms —
most likely the
CSequencemotion-queue / transition +pending_motions/MotionDone, and the inbound position/dead-reckoning where it deviates. Tests-first (parity tests before behavior). Integrate the sequencer SURGICALLY — change the minimum; do not replace the whole transform/cycle pipeline at once. - Verify: the walk↔run transition is smooth and no cascading animation/position desync — user visual + retail-observer side-by-side.
Live-capture setup (structured testing)
- acdream = OBSERVER (login as
+Acdream); the other player driven from a retail client (retail packets = ground truth, so any render artifact is a pure acdream inbound bug). - Launch env (PowerShell): the standard live vars +
ACDREAM_DUMP_MOTION=1+ACDREAM_REMOTE_VEL_DIAG=1(heavy; dumps[UM_RAW]/[SETCYCLE]/[OMEGA_DIAG]/[VEL_DIAG]/[SEQSTATE]/[UPCYCLE]so you can correlate each inbound packet with what acdream renders). - Structured protocol, one motion at a time: walk-straight (start→stop), run-straight, turn-in-place, curved path, idle, walk↔run toggle (the key one), abrupt-stop-from-run.
- NOTE:
+Acdreamhadrun=15225(GM-buffed) this session → absolute speeds unrepresentative; judge relative behavior + transitions.
Housekeeping
- Close the running observer acdream client before the new session rebuilds
(it locks
AcDream.App.exe;dotnet buildfails with the DLL-copy lock otherwise — the user closes it, we do NOT kill it). - A background research agent (mapping acdream's inbound animation handling) was in-flight when this session stopped — orphaned; the new session re-does the mapping cleanly.
Discipline reminders
- The user's side-by-side retail observations are axioms (retail-oracle); once a mechanism plan exists, artifacts become acceptance tests, not new investigations (no whack-a-mole).
- Report-only until fixes approved. Decomp-verbatim. Tests-first.
- Every deviation the port introduces/retires updates
docs/architecture/retail-divergence-register.mdin the same commit.