feat(physics): C4 route 4a — remote steady-state Position through the seam
Routes the classifier's two NO-PLACEMENT remote branches — Interpolate (contact, PlayerDistance < 96 m) and NoPositionOperation (no contact) — through a Runtime-owned seam, and fixes the two divergences they carried. Teleport, far-snap and cell-less stay on the legacy App path; 4b owns them. Route 4 was split into 4a/4b after scoping put the whole route at 1,500-2,500 lines against a ~400 budget. 4a's branches perform no SetPosition, so this slice carries no deferred-cell park, no service-window guard and no allocation exposure — which is what made the split worth doing. Divergences fixed, both previously unfiled: * D1 — the NPC airborne branch hard-snapped Body.Position/Orientation and branched on the client-tracked rmState.Airborne, never consulting the wire IsGrounded bit. Retail's MoveOrTeleport @0x00516330 returns 0 at 0x0051636D and writes nothing. Player remotes were already correct; NPCs were not. * D2 — ConstrainTo was armed before the operation, unconditionally, so it fired on the airborne no-op retail skips and anchored to the PRE-move position. Retail arms it at 0x00454272, only when MoveOrTeleport returns nonzero, anchored to &arg2->m_position read live, i.e. post-move. AP-87 and TS-44 were carried deliberately, not delegated away. AP-87's three conditions — including firstUp, which one round silently dropped — are preserved as an explicit acdream policy layer applied AFTER the classifier commits to Interpolate; the two previously separate player/NPC copies are now one. TS-44 stays an NPC-only caller gate; extending sticky suppression to player remotes has no retail basis and no live evidence, so it was declined rather than absorbed. Landing is explicitly carved out of 4a's ownership on both arms. A landing packet classifies Interpolate, so an ordering slip would ENQUEUE a body that must PLANT and a creature knocked off a ledge would glide down over a packet interval. The carve-out is a named entry point returning AirborneSnap/SteadyStateInterpolate/ Legacy precisely so the PRECEDENCE is observable and testable rather than implied by statement order — that is how the slip happened once and was caught. The player/NPC asymmetry on landing is real and NOT resolved here: retail draws no such distinction, but converging them is a behaviour decision needing its own evidence. Filed into the 4b plan. Register: AP-135 filed for the two bookkeeping writes the airborne branch deliberately retains (rmState.CellId, LastServerPos/Time) — not retail's model, but load-bearing for our catch-up sweep and staleness timer, and verified not to be a canonical cell commit for ordinary remotes. AP-87 and TS-44 rewritten to describe the code. Honest remainder: App still owns branch selection, the airborne return, the cell write, the entity write and the shadow publish, and headless satisfies "both hosts drive the identical entry point" only vacuously since it returns early for remotes. That is written into the 4b bullet rather than left implicit. Cost: 364 non-comment production lines, 91% of the ~400 budget — the split did isolate the cheap half, but not by much. Do not carry "well under" into 4b's scoping. Gates: complete Release solution 10,938 passed / 4 skipped / 0 failed (pre-4a baseline 10,909). Four review rounds; the first three each introduced a new behavioural defect while fixing another, and each left a comment asserting behaviour that no longer matched — the final round's precedence matrix was traced cell-by-cell against HEAD with only the D1-intended difference. App tests call production entry points against a real WorldEntity and real classifier output, closing route 2's #292 gap rather than repeating it. Connected acceptance NOT run — needs a live second character. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
19d9509497
commit
44830a0eb3
12 changed files with 1854 additions and 150 deletions
|
|
@ -270,6 +270,35 @@ same commit) → docs/handoff commit. No workarounds; no fused slices.
|
|||
Position-time service-window guard, #277's broken bound, N3 (headless never
|
||||
calls `RetryPending`), and the third divergence (`ConstrainTo` never armed
|
||||
on the remote teleport branch) all live.
|
||||
|
||||
**4b also inherits 4a's ownership remainder — scheduled here, not implied
|
||||
by code comments.** Two independent reviews flagged that 4a satisfies
|
||||
contract items 1 and 2 only partially, and the plan must carry that rather
|
||||
than leaving it in `// 4b deletes this fallback` comments:
|
||||
- Runtime owns the classification, the request construction (one shared
|
||||
builder, `RuntimeAcceptedPositionRouteRequests`), the near-InterpolateTo
|
||||
decision with AP-87, and the post-operation `ConstrainTo`. **App still
|
||||
owns** branch selection, the airborne early return, the
|
||||
`RemoteMotion.CellId` write, the `WorldEntity` pose write, and the
|
||||
collision-shadow publish — all in `LiveEntityNetworkUpdateController`.
|
||||
- Item 2 ("both hosts drive the identical Runtime entry point") is
|
||||
satisfied only VACUOUSLY: `RuntimeLiveEntitySessionController` returns
|
||||
early for remotes, so no no-window host exercises this path at all and
|
||||
nothing can diverge yet. That stops being true the moment a headless
|
||||
host needs remote motion.
|
||||
- Every legacy fallback 4a deliberately left in place is 4b's to delete:
|
||||
the pre-operation unconditional `ConstrainTo`, the player arm's
|
||||
`!update.IsGrounded` no-op, the player and NPC legacy near/far routing
|
||||
(each still carrying its own duplicate `96f` / `4f` constants), and the
|
||||
airborne-precedence carve-out
|
||||
(`LiveEntityNetworkUpdateController.ApplyRemoteContactRouting`) that
|
||||
keeps a landing body snapping. Retiring the last one is a real behaviour
|
||||
decision — retail makes no player/NPC distinction there — and needs its
|
||||
own live evidence, not a silent convergence.
|
||||
- Register row **AP-135** (the airborne no-op's retained acdream
|
||||
bookkeeping: the server cell id for the free-fall sweep gate, and the
|
||||
last-server-position sample) retires with 4b's transition machinery, not
|
||||
before.
|
||||
Note the route-4 Create half is ALREADY DONE (C3b/C3c); the remaining work is
|
||||
steady-state remote Position plus the deletions. AP-131 is NOT retired by
|
||||
either sub-slice — see the scoping doc for why route 4 alone cannot.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue