|
Download docs/research/QVM_CLIENT_TIMER_BATCH.md from nmarshall/urt-rs: direct link, hf CLI and curl.
- Browser
- Download file 8.79 kB
-
https://huggingface.co/nmarshall/urt-rs/resolve/main/docs/research/QVM_CLIENT_TIMER_BATCH.md
- Command line
-
hf download hf://nmarshall/urt-rs/docs/research/QVM_CLIENT_TIMER_BATCH.md
-
curl -L -o QVM_CLIENT_TIMER_BATCH.md https://huggingface.co/nmarshall/urt-rs/resolve/main/docs/research/QVM_CLIENT_TIMER_BATCH.md
8.79 kB
| # Client timer body and caller preparation: RE-964–973 | |
| Ten tasks recover five source/Rust contracts across **760 paired fixtures**. They extend the [filter-command/frame-prefix batch](QVM_FILTER_COMMANDS_BATCH.md) through the complete persistent-state body of150692 and the timing-preparation prefix of its caller154089. Each task has its own commit and focused `cargo xtask` checks. Native time replies are supplied, and damage effects remain captured requests against supplied health. | |
| | Tasks | Evidence | Paired fixtures | | |
| | --- | --- | ---: | | |
| | RE-964 / RE-965 | [Original deadline fragments](QVM_CLIENT_TIMER_TERMINAL.md) / [Rust fragments](RUST_CLIENT_TIMER_TERMINAL.md) | 144 | | |
| | RE-966 / RE-967 | [Original phase loop](QVM_CLIENT_TIMER_TICKS.md) / [Rust loop](RUST_CLIENT_TIMER_TICKS.md) | 288 | | |
| | RE-968 / RE-969 | [Original countdown/recovery](QVM_CLIENT_TIMER_RECOVERY.md) / [Rust recovery](RUST_CLIENT_TIMER_RECOVERY.md) | 216 | | |
| | RE-970 / RE-971 | [Original complete timer body](QVM_CLIENT_TIMER_COMPLETE.md) / [Rust composition](RUST_CLIENT_TIMER_COMPLETE.md) | 16 | | |
| | RE-972 / RE-973 | [Original caller preparation](QVM_CLIENT_TIMER_PREPARE.md) / [Rust preparation](RUST_CLIENT_TIMER_PREPARE.md) | 96 | | |
| ## Deadline and phase-loop findings | |
| The first contract executes two explicit fragments:150791..150810 before the loop, and151085..151131 after it. Entity cooldown seconds multiply by1000 and add to a timestamp using word wrap before signed comparison with the game tick. Exact equality retains the entity flag; strictly older values clear it. The terminal fragment clears client mask2 only after a strict deadline, preserves unrelated bits and timestamp words, and adds milliseconds to a wrapping total counter. These fragments are kept separate in the Rust API so the complete timer can place them around the loop in source order. | |
| The100ms loop consumes signed residual values while they are at least100. Each iteration increments a phase word with wrap and computes signed remainder using a table indexed by rate-1. Rates1..5 select9,4,3,2,1. Rate0 reads the preceding word, whose raw value is1120403456, also the bit pattern for100.0f32. That word is used as an integer divisor. The port preserves the alias; unsupported rate/table domains reject explicitly. | |
| Flag256, positive supplied health and phase zero cause a damage request. The source requests target entity, owner as both inflictor and attacker, null direction/point, amount1, flags0, means word23 and the entity weapon word. These arguments are projected from actual211239 calls. The callback effect is captured, so repeated loop decisions continue to use supplied health. Actual health/death effects and feedback into the loop remain open. | |
| ## Float countdown and recovery ordering | |
| The full loop contract adds flags512/256/128, repeated f32 subtraction of0.1 and associated status/rate resets. Initially nonpositive countdown with flag256 clears that flag, sets rate0 and stores zero. Positive countdown subtracts one f32 step per iteration; crossing zero also clears flag256 and resets rate/countdown. | |
| A positive countdown that crosses zero jumps to the loop boundary before secondary flag128/status cleanup. That cleanup can occur on a later iteration. An initially nonpositive countdown can reach it in the same iteration. Clearing flag128 also clears status mask1. Rate reset0 changes the divisor for following iterations through the preceding-word alias. Source fixtures verify exact float words, phase progression and unrelated bits. Gameplay names and ownership for these raw status fields still need caller/structure evidence. | |
| Rust supports finite countdowns and bounded residual/rate domains, stages unsupported inputs without partial mutation, and retains the original ordering. The earlier flag512-disabled cases remain regressions of the expanded API. | |
| ## Complete timer composition | |
| The16 whole-body probes execute150692 through its void-return boundary at151131. Actual65613 horizontal squared-motion and252067/251995 expiry children execute; native time is supplied and damage211239 remains captured. The persistent write set covers activity and entity-bit copies, the shared residual, entity cooldown, loop flags/status/rate/phase/countdown, terminal flags and elapsed total, plus all4096 filter rows through table-wide checksums. | |
| The residual is one source word: prefix milliseconds accumulate into it before100ms consumption. Rust models that ownership once and composes prefix/expiry, pre-loop deadline, the full tick loop and terminal tail in order. Time acquisition precedes damage requests. The contract retains count-zero expiry, unchanged velocity/last-motion words, duplicate flag updates and wrapping totals. Typed errors roll back the staged table and client state together. | |
| This recovers the complete timer body's finite persistent-state behavior under the stated child boundaries. It does not establish actual native clock acquisition, damage/health execution, network behavior or the complete caller154089. | |
| ## Caller preparation | |
| The direct timer call is at155714 inside154089. This batch executes only the caller prefix154090..154210, with155716 as a separate early-return boundary. It does not jump over or claim the intervening processing before timer dispatch. | |
| The prefix requires connection word468 to equal2. It then copies the game tick and original command timestamp into client words6172/6176, clamps command time sequentially against tick+200 and tick-1000 using signed wrapping arithmetic, and computes a delta from the current command-time word. A delta below1 exits unless word3108 equals2. A proceeding delta above200 caps at200. | |
| If quantization word712 is nonzero, the command timestamp then rounds using `(command+7)/8*8` with original signed arithmetic. The delta is not recomputed after rounding. Source cases demonstrate a rounded timestamp of10000 with a retained delta9, and a permitted negative delta through the word3108 exception. Rust preserves disconnected state, original timestamp copies, exact early-gate mutations and sequential bounds under wrap. Semantic field ownership and the remaining caller paths are still open. | |
| ## Validation | |
| Each task ran its focused `cargo xtask test-group` before its commit: qvm/rust-client-timer-terminal, qvm/rust-client-timer-ticks, qvm/rust-client-timer-recovery, qvm/rust-client-timer-complete and qvm/rust-client-timer-prepare. Selected reports regenerated twice identically. Independent word arithmetic, loop/flag and composition expectations check original probes; Rust reports compare every projected field against its source report and record its SHA256. | |
| Rust regressions also cover signed cooldown wrap, strict equalities, phase wrap/remainder, exact damage arguments, preceding-word rate alias, delayed cleanup, unsupported float/rate rollback, whole-timer state/table rollback, disconnected caller state, nonpositive-delta exception and post-delta rounding. Dependency-selection regressions include all five source/Rust pairs and shared 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 c1e91e2e` run after task ten passed: **1,878 Python tests**, **270 Rust tests** (assets10, gameplay230, xtask30), **106 deterministic report producers**, storage policy, links across **546 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 the batch. | |
| ## Historical next work after RE-973 | |
| - [ ] Recover caller154089 after154210 through155714, including all alternate exits, callbacks and any later changes to timing/state before timer dispatch. | |
| - [ ] Resolve211239 damage effects and health/death feedback inside the loop, plus field/status ownership and the complete source rate/countdown lifecycle. | |
| - [ ] Extend timing-prefix wrap/quantization domains, invalid rate/table provenance, nonfinite floats and larger residual budgets with source-backed probes. | |
| - [ ] Recover initialization3877 around loader252933, table reset/ownership ordering, native time ABI/calendar rollover and actual expiry/frame cadence. | |
| - [ ] Attach real time/damage/file/userinfo/queued-command/network adapters and validate operation order/failure behavior on macOS/Linux. | |
| - [ ] Continue bot setup125185, userinfo171668, ranking5864, native collision, respawn/intermission/events/scoreboard, asset conversion and Rust/Bevy/Solari runtime acceptance. | |
| Follow-up: [RE-974–983 pre-movement processing findings and current next work](QVM_CLIENT_PROCESSING_BATCH.md). | |