File size: 8,853 Bytes
99a6f51 ad83778 99a6f51 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | # Client routing and pre-movement processing: RE-974–983
Ten tasks recover five source/Rust contracts across **328 paired fixtures**. They extend the [client timer/caller preparation batch](QVM_CLIENT_TIMER_BATCH.md) from timing preparation through routing, command rewriting, actual inactivity policy and movement-parameter setup. Each task has a separate commit and focused `cargo xtask` validation. Native intermission/spectator/team/send/drop effects remain captured; actual movement execution is beyond the boundary.
| Tasks | Evidence | Paired fixtures |
| --- | --- | ---: |
| RE-974 / RE-975 | [Original routing](QVM_CLIENT_ROUTING.md) / [Rust routing](RUST_CLIENT_ROUTING.md) | 16 |
| RE-976 / RE-977 | [Original command rewrite](QVM_CLIENT_COMMAND_REWRITE.md) / [Rust rewrite](RUST_CLIENT_COMMAND_REWRITE.md) | 48 |
| RE-978 / RE-979 | [Original inactivity](QVM_CLIENT_INACTIVITY.md) / [Rust inactivity](RUST_CLIENT_INACTIVITY.md) | 120 |
| RE-980 / RE-981 | [Original movement setup](QVM_CLIENT_MOVEMENT_SETUP.md) / [Rust setup](RUST_CLIENT_MOVEMENT_SETUP.md) | 96 |
| RE-982 / RE-983 | [Original composed prefix](QVM_CLIENT_PRE_MOVEMENT.md) / [Rust composition](RUST_CLIENT_PRE_MOVEMENT.md) | 48 |
## Routing and rewritten command ownership
At154210, a nonzero intermission word takes precedence and requests151133 with the client pointer. Otherwise team word3 or a nonzero follow word enters spectator routing. Spectator word3 returns without invoking149671; other values request149671 with entity and command pointers, then return. Normal clients continue at154256. Callback effects are captured, and explicit boundaries stop at154256 or the source early return155716.
Command rewriting locks when pause mask1 is set or mode10 combines with client mask16. A locked command restores saved angle words and clears buttons plus movement bytes493..495. An unlocked command updates the saved angles from current input. A separate server override can clear buttons/movement after either angle path. All partial-byte writes preserve adjacent byte492, and this fragment leaves command time unchanged. Other pause bits alone do not select this lock. The48 source cases use high-bit angle and movement words to verify raw-bit preservation.
## Inactivity policy
Actual150382 is now source-executed across120 cases. Entity mask8 bypasses the policy. Disabled idle configuration stores tick+60000 and clears warning state. Any nonzero pause word clamps the deadline upward against a pause anchor plus configured seconds×1000; it does not clear warning state. Movement in any signed command byte or attack mask1 clamps against the current tick plus the same interval and clears warning state. Activity does not shorten an already-later deadline.
Dead/nonpositive-health clients extend the deadline by supplied milliseconds before the exemption check. Other exempt clients retain state. Timeout requires tick strictly greater than deadline. Mode1 requests a team change using source string `s`, then sends the original spectator notification; other modes request a native drop. The function returns false on timeout while callback effects remain captured.
Within the last ten seconds, a strict warning-boundary comparison and zero warning word emit a mode-specific message and latch the warning. Exact boundary equality does not warn, exact deadline equality does not time out, and repeated warnings are suppressed. All arithmetic wraps as words before signed comparisons. Fixtures cover negative/wrapping configuration, nonzero negative movement bytes, other buttons, pause mask2, dead-client wrap, exemptions and effect order. Callback bodies and actual client removal/team mutation remain open.
## Movement parameter setup
At154405, the noclip word takes precedence over nonpositive health when selecting the movement-type word; ordinary live clients select0. Pause mask1 stores zero gravity/speed. Unpaused paths convert the base f32 gravity to an integer, optionally after multiplying by a supplied controller factor, then set speed220. The controller pointer is consumed only on the unpaused path. Finite negative conversion truncates toward zero; unsafe conversion/nonfinite domains reject in the Rust API without mutation.
Two player words use raw `low | (high << 8)` operations without byte masking. High bits therefore survive beyond an assumed two-byte encoding. The prior event sequence is saved for later processing. The96 source cases verify these values and stop at154544 before movement scratch initialization, mode callbacks or physics.
## Composed source prefix
The48 composed probes execute154089 from timing preparation through154544, or stop at the original early-return boundary155716. Source routing callbacks remain captured, but the150382 inactivity body executes with the current rewritten command. No intervening processing within this range is skipped.
- Timestamp preparation retains the pre-round millisecond delta, including the allowed negative exception, and passes that value to inactivity.
- Routing exits retain preceding timestamp copies and command-time clamps/rounding while skipping command rewriting and inactivity.
- Server command blocking can erase movement before the inactivity check and turn a previously active command into a timeout.
- Ordinary inactivity rejection retains preceding timestamp and command mutations while leaving movement setup untouched.
- Warning paths can continue into movement setup; timeout paths return earlier.
- Pause semantics differ by consumer: command/movement setup test mask1, while inactivity tests any nonzero pause word.
Rust models shared timestamp/spectator fields once, derives movement bytes from the rewritten command word, and preserves ordinary early-exit mutations. Unsupported typed domains stage the complete state and effect plan atomically. These policies do not execute native effects. The source and Rust reports compare timing, angles, saved input, packed bytes, inactivity state, movement parameters, event-sequence capture and ordered effects.
## Validation
Each task ran its own focused `cargo xtask test-group` before its commit: qvm/rust-client-routing, qvm/rust-client-command-rewrite, qvm/rust-client-inactivity, qvm/rust-client-movement-setup and qvm/rust-client-pre-movement. Selected reports regenerated twice identically. Independent routing, arithmetic, command-byte and composition expectations check original probes; Rust parity compares every projected field with its source report and records the report SHA256.
Rust unit tests additionally cover routing precedence, saved-angle direction, byte preservation, strict/repeated warnings, team-before-message ordering, wrapped dead-client extension, paused unused float inputs, one-shot controller consumption, high-bit packing, late-error rollback and preceding writes on ordinary early exits. Dependency-selection regressions include all five source/Rust pairs and shared processing/timer/command/loading/lifecycle/native-policy/formatter inputs, including scoped gameplay test-count metadata. Python uses the flake-declared Nix runtime throughout, including Git hooks. Original assets are unchanged. The single `cargo xtask test-full --since 74af72a2` run after task ten passed: **1,898 Python tests**, **280 Rust tests** (assets10, gameplay240, xtask30), **111 deterministic report producers**, storage policy, links across **557 documentation files** and whitespace guards. Regeneration left no changes. Focused dependency-selection regression also passed. Validation notes are amended into task ten, preserving ten commits for this batch.
## Follow-up from RE-984
Scratch initialization, input masks, actual linked-overlap checks and native context assembly are now covered by the [RE-984–993 batch](QVM_MOVE_CONTEXT_BATCH.md). Actual movement54475 and callback bodies remain open. The original follow-up scope was:
- [ ] Recover154544 onward: movement scratch initialization, mode10 callbacks152792/152673, mode8 callback153419, remaining input masks and the actual movement/collision dispatch.
- [ ] Resolve routing151133/149671 and team183102 callback bodies, including state feedback and all alternate caller exits through timer dispatch155714.
- [ ] Connect211239 damage/health feedback with the complete timer, plus native time, file, userinfo, queued commands and network adapters.
- [ ] Extend inactivity wrap/configuration and float/conversion domains, field ownership, actual pause lifecycle and source-backed long-running acceptance scenarios.
- [ ] Recover initialization3877/table ownership, native time ABI/calendar behavior and complete client/frame scheduling.
- [ ] Continue bot setup125185, userinfo171668, ranking5864, native collision, respawn/intermission/events/scoreboard, asset conversion and Rust/Bevy/Solari acceptance on macOS/Linux.
|