acdream/docs/research/2026-08-01-runtime-set-position-authored-mover-preparation.md

106 lines
5.4 KiB
Markdown

# Runtime SetPosition authored mover preparation - 2026-08-01
## Scope
This is placement Slice 4B2 checkpoint 3. It adds the dormant,
presentation-independent preparation contract used to turn an accepted Runtime
position into retail's exact `CPhysicsObj::SetPosition` mover input. No App or
Headless production route consumes the contract yet, so game behavior is
unchanged and AP-1/AD-1 remain open.
## Retail oracle
The implementation was checked against the named September 2013 client:
- `PhysicsDesc::PhysicsDesc` `0x0051D4D0`
- `PhysicsDesc::UnPack` `0x0051DDD0`
- `CPhysicsObj::set_description` `0x00514F40`
- `CPhysicsObj::SetPosition` `0x005160C0`
- `SPHEREPATH::init_sphere` `0x0050C670`
- `CPartArray::GetNumSphere` `0x00518060`
- `CPartArray::GetSphere` `0x00518070`
- `CPartArray::GetStepUpHeight` `0x005180D0`
- `CPartArray::GetStepDownHeight` `0x005180F0`
- `CTransition::init_object` `0x00509E40`
- `OBJECTINFO::init` `0x0050CF30`
SetPosition calls `CTransition::init_object(..., state = 0)` directly. It does
not use the ordinary-movement `CPhysicsObj::get_object_info` path. Consequently
the SetPosition state carries the player/PK/PKLite/impenetrable classifications
(plus acdream's pointer-free entry-restriction carrier), but it does not add
Contact, OnWalkable, PathClipped, FreeRotate, or EdgeSlide. Ethereal and
`step_down = !Missile` are separate `OBJECTINFO` fields derived from the current
physics state.
## Exact preparation contract
- Runtime captures the complete accepted server frame under the exact entity,
session, position, vector/velocity, wire-state, final-physics-state mutation,
object-description, and create-integration authorities. A host cannot
substitute a second position.
- Collision-world X/Y uses the target landblock's active live-centered offsets;
full cell ID, cell-local XYZ, and the complete quaternion remain unchanged.
- Setup resolution is bound to the canonical Setup DID. A known but unavailable
Setup remains retryable. Resolved-absent is valid only when the canonical
object has no Setup. An authored empty Setup remains distinct and still
contributes its scaled StepUp/StepDown heights.
- The complete ordered Setup sphere list is retained. Core later applies
retail's `min(count, 2)` traversal cap. The successfully resolved no-PartArray
or zero-sphere arm reaches Core with an empty list, where SetPosition supplies
the retail dummy sphere `(0,0,0.1)`, radius `0.1`, scale `1.0`.
- Scale precedence is `PhysicsDesc.Scale ?? EntitySpawn.ObjScale ?? 1.0`.
Present zero and finite negative values are preserved. Scale is not consumed
by a resolved-absent dummy mover.
- Every authored command is sealed to the exact preparation operation. Manual,
stale, replaced, or merely value-equivalent commands cannot bypass the seal.
- A wire-state, final-state mutation (including NoDraw and missile-stop),
vector/velocity, description, or create change during a deferred cell wait
returns the resident to `AwaitingPreparation`; the stale mover is never
replayed when the collision generation wakes.
- Preparation mutates no body, clock, FullCell, spatial/shadow registration,
bucket, camera, world entity, or presentation resource.
Legacy direct SetPosition remains a distinct token mode so the dormant slice
does not change existing call sites or their warmed allocation ceiling. If a
legacy operation becomes deferred and later needs new authored data, the
presence of Runtime's preparation authority makes the exact seal mandatory.
## Ownership and validation
`RuntimeSetPositionState` owns one exact-key preparation-authority entry only
for operations which require authored preparation. The entry dies with the
operation on replacement, acknowledgement, cancellation, delete, session
reset, or disposal and participates in terminal convergence accounting.
Preparation-only validation checks the exact cell frame, live-centered world
position, values consumed by the first two retail spheres, Setup-derived step
heights, line/scatter inputs, and bounded scatter attempts. The legacy direct
validator retains its prior behavior, including retail's dummy-sphere and
first-two-sphere semantics.
## Gates and review
- Focused authored-mover plus SetPosition residence tests: 80/80.
- Runtime Release build: zero warnings and zero errors.
- Complete Runtime project under invariant culture: 595/595.
- Complete Release solution with installed DAT/pak fixtures: 10,342 passed /
4 intentional skips.
- Retail-conformance review: canonical frame, DID binding, scale/step/sphere
behavior, exact SetPosition flags, and deferred wake checked against the
named addresses above.
- Architecture/adversarial review: command sealing, legacy promotion,
replacement, deferred wake, direct compatibility, allocation, reset, GUID
reuse, and ownership convergence checked.
The three ordinary current-culture Runtime failures are pre-existing Swedish-
locale formatting assumptions (`0,5` versus `0.5` and localized sky text); the
same complete project passes under invariant culture.
## Next checkpoint
Implement the dormant atomic local-player physics publication transaction:
prepare a private controller/body/clock without canonical mutation, evaluate
SetPosition against that candidate, then publish the exact same body relation
to `RuntimeEntityRecord` and `RuntimeLocalPlayerMovementState` in one callback-
free Runtime commit. App and Headless production activation remains a later
checkpoint.