# Slice J5.4 — canonical local movement ownership **Date:** 2026-07-26 **Parent:** `docs/plans/2026-07-26-modern-runtime-slice-j5.md` **Scope:** ownership relocation only; no movement, collision, animation, or wire behavior changes ## Retail oracle The named September 2013 client remains the oracle: | Mechanism | Named symbol | Address / named pseudo-C | |---|---|---| | take local control | `CommandInterpreter::TakeControlFromServer` | `0x006B32D0`, lines 699046–699145 | | apply current raw movement | `CommandInterpreter::ApplyCurrentMovement` | `0x006B3430`, lines 699146–699530 | | stop decision | `CommandInterpreter::MaybeStopCompletely` | `0x006B3B90`, lines 699531–699563 | | post-inbound position slot | `CommandInterpreter::UseTime` | `0x006B3BF0`, lines 699564–699645 | | input command boundary | `CommandInterpreter::MovePlayer` | `0x006B3F40`, lines 699803–700232 | | AP predicate | `CommandInterpreter::ShouldSendPositionEvent` | `0x006B45E0`, lines 700233–700273 | | MTS serialization | `CommandInterpreter::SendMovementEvent` | `0x006B4680`, lines 700274–700315 | | AP serialization | `CommandInterpreter::SendPositionEvent` | `0x006B4770`, lines 700316 onward | | object/root-motion step | `CPhysicsObj::UpdatePositionInternal` | `0x00512C30`, lines 280817 onward | | object update envelope | `CPhysicsObj::update_object` | `0x00515D10`, lines 283950 onward | The detailed wire unpack/pack interpretation and prior ACE/Holtburger cross-checks are retained in: - `docs/research/2026-05-04-l3-port/02-um-handling.md`; - `docs/research/2026-05-04-l3-port/14-local-player-audit.md`; - `docs/research/2026-05-01-retail-motion-trace/findings.md`; - `docs/research/2026-07-26-slice-j5-owner-and-retail-order-inventory.md`. The reference source trees are not present in this worktree, so J5.4 reuses those already-recorded cross-checks rather than inventing a new interpretation. No behavioral algorithm is changed by this slice. ## Consolidated retail pseudocode ### Input / object phase ```text MovePlayer(command, speed, hold, ...) if server currently controls movement TakeControlFromServer() mutate the player's one RawMotionState / MotionInterpreter apply the current movement to the same CPhysicsObj if the movement boundary requires a report SendMovementEvent() SendMovementEvent() require player + SmartBox + raw motion state + autonomous movement snapshot complete raw motion state snapshot the player's canonical cell-local Position and contact snapshot instance/server-control/teleport/force-position sequences serialize and send MoveToState stamp only last_sent_position_time after successful send ``` Jump uses the same pre-inbound input/object phase. The charged extent and body-local launch velocity are read from the canonical local controller and serialized exactly once on release. ### Object simulation ```text UpdatePositionInternal(dt, rootFrame) apply the animation-authored root frame to the canonical physics body integrate/transition through the existing retail physics pipeline commit complete Position, velocity, contact, and cell membership update_object() advance the retail object clock in fixed quanta update movement and physics in retail order leave one committed canonical body for every later borrower ``` App animation may supply the authored root frame and consume the committed pose. It does not own a second body, movement state, or object clock. ### Post-inbound autonomous position phase ```text UseTime() after inbound messages may have corrected the canonical body: if ShouldSendPositionEvent() SendPositionEvent() ShouldSendPositionEvent() compare current cell/contact against the last AP baseline after the retail interval, compare the complete current Frame SendPositionEvent() snapshot canonical cell-local Position, orientation, contact, timestamps serialize and send AutonomousPosition after successful send: stamp last_sent_position_time copy complete Position and contact plane into the AP baseline ``` This preserves the accepted acdream frame order: 1. graphical or no-window input becomes a typed `MovementInput`; 2. Runtime mutates the canonical controller/body; 3. Runtime emits MTS/jump before inbound dispatch; 4. inbound corrections mutate that same body; 5. Runtime evaluates/emits AP after inbound dispatch; 6. App projects the final committed body to animation, camera, and UI. ## Ownership result - `PlayerMovementController`, its movement data types, and `LocalPlayerOutboundController` now live in `AcDream.Runtime.Gameplay`. - `RuntimeLocalPlayerMovementState` is the sole controller, construction motion seam, autorun latch, typed view, and terminal ownership ledger. - `DispatcherMovementInputSource` samples physical held state only and maps configured edges onto the Runtime owner. - direct Runtime movement commands and graphical input mutate that same autorun state. - `PlayerMovementConstructionOptions` replaces process environment reads and is populated from `RuntimeMovementSkillState`. - the App diagnostic implementation crosses only `IMovementTruthDiagnosticSink`. - shutdown retires graphical/session borrowers before disposing the Runtime movement owner. ## Preserved boundaries - Silk input, mouse filtering, camera, CSequence/PartArray presentation, retained jump bar, sounds, and effects remain in App. - `PhysicsEngine` remains App-owned until J5.5. - remote movement and projectiles remain App-owned until J5.5/J5.6. - TS-33's already-recorded possible same-update MTS/AP ordering difference is preserved; this ownership move neither widens nor hides it. ## Closeout evidence - Runtime state/view identity, two-instance isolation, construction lease, terminal convergence, typed movement skills, and zero-allocation snapshots; - graphical/direct autorun parity and one-production-owner source guards; - existing bit-exact RawMotionState, MTS, jump, AP, quaternion, contact, and strict cadence tests; - existing run/walk/back/strafe/turn/mouse-look/jump/land, short-tap, portal/reset, target-facing, and repeat-abort tests; - Release build, complete solution tests, exact-binary connected lifecycle, and canonical movement route. All required gates pass on production commit `aa3f4a60f87f2cbebc3d8ecd5e33d779b7fb13c1`: - Runtime: 303 passed; - App: 3,716 passed / 3 intentionally skipped; - complete Release solution: 8,575 passed / 5 intentionally skipped; - connected lifecycle/reconnect: `logs/connected-world-gate-20260726-123425/report.json`, exact source/binary commit, two graceful code-zero sessions, 7/7 readiness checkpoints, and zero failures; - canonical movement route: `logs/connected-r6-soak-20260726-124049.report.json`, exact source/binary commit, all nine destinations materialized, forward/jump/combat/movement- truth exercises passed at Caul, Holtburg, and Caul return, and graceful code-zero shutdown. The separate baseline-test correction `3456dff0` makes the retained streaming test accept the already-shipped Slice-E cursor-budget contract: retirement may converge in the current or a following tick. It is not part of the J5.4 production rollback. Exact J5.4 rollback: ```text git revert aa3f4a60f87f2cbebc3d8ecd5e33d779b7fb13c1 ```