Move the canonical local movement controller, body/motion managers, object clock, movement wire data, and MTS/jump/AP sender into AcDream.Runtime. Replace process skill defaults with typed Runtime character options, make graphical and direct commands borrow one autorun owner, retain the construction-time PartArray seam, and include movement in terminal ownership convergence. Preserve the accepted pre-inbound movement/jump and post-inbound autonomous-position order while moving the exact packet/cadence fixtures into Runtime tests. Add graphical/direct parity, two-instance isolation, teardown, allocation, architecture, and divergence-path coverage. Co-authored-by: Codex <noreply@openai.com>
146 lines
6.2 KiB
Markdown
146 lines
6.2 KiB
Markdown
# 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.
|
||
|
||
## Automated evidence required before closeout
|
||
|
||
- 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.
|