5.4 KiB
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::PhysicsDesc0x0051D4D0PhysicsDesc::UnPack0x0051DDD0CPhysicsObj::set_description0x00514F40CPhysicsObj::SetPosition0x005160C0SPHEREPATH::init_sphere0x0050C670CPartArray::GetNumSphere0x00518060CPartArray::GetSphere0x00518070CPartArray::GetStepUpHeight0x005180D0CPartArray::GetStepDownHeight0x005180F0CTransition::init_object0x00509E40OBJECTINFO::init0x0050CF30
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), radius0.1, scale1.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.