106 lines
5.4 KiB
Markdown
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.
|