guest sdk: large-room callbacks — roster-epoch ctx mode + declared heartbeats + Rust parity#27
Merged
Merged
Conversation
…artbeats + Rust parity The kit half of the large-room-callbacks OpenSpec change. Three pieces: Ctx roster-epoch mode (negotiated via GameMeta.CtxFeatures bit 0): the member section gains sentinel forms — count 0xFFFE = full roster at a u32 epoch, 0xFFFF = unchanged-since-epoch (6 bytes total) — emitted only to guests that declare the feature; legacy guests stay byte-identical and real counts (<= 0xFFFD) keep the legacy layout, so all four host/guest version pairings are unambiguous. Both SDKs decode the sentinels into an epoch-aware roster cache: zero member allocations on the unchanged form (the byte-skim cache stays for pre-feature hosts), full forms are authoritative, and an epoch mismatch degrades to the cached roster with a single warning, never a trap. ABI major stays 2 (ABI.md §4.1). GameMeta.HeartbeatMS: games declare their wake cadence (validated 0 or 20..1000 at meta encode, the config-specs fail-fast posture). It rides a new always-written, presence-guarded meta trailer with the features bitset (ABI.md §4.2); shellcade-kit play honors it locally; host precedence is admin config > declaration > 50ms default. Rust crate parity: mirrors the meta fields, sentinel decode, and an Rc-shared epoch roster cache — and picks up the v2.5.0 Go-only baseline work it missed: ROSTER_CAP 16 -> 1024 with lazily-allocated per-slot baselines and allocated-only broadcast reconcile. Golden vectors pin Go/Rust meta encodings byte-identical (trailer bytes cross-checked against the Go encoder). GUIDE.md gains the large-room authoring section (declare heartbeat + feature, render-on-change dirty tracking, Members() lifetime). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The kit half of the large-room-callbacks change (engine half follows; design lives in the platform's spec workspace). Targets the two measured per-callback costs in large rooms plus heartbeat flexibility.
1. Ctx roster-epoch mode — opt-in via
GameMeta.CtxFeaturesThe host re-sends the full member list in every callback payload (~100KB/callback at 1000 players — the dominant input-path cost, and the residual
-gc=leakingleak). Withkit.CtxFeatRosterEpochdeclared, the member section becomes sentinel-keyed (ABI.md §4.1):memberCount0x0000..0xFFFD0xFFFEu32epoch0xFFFFBoth SDKs decode the sentinels into an epoch-aware roster cache (zero member allocations on the unchanged form); full forms are authoritative; an epoch mismatch logs once and degrades to the cached roster. Legacy guests never see the new forms; pre-feature hosts keep working via the retained byte-skim cache. ABI major stays 2.
2.
GameMeta.HeartbeatMS— declare your tickValidated (0 or 20..1000) at meta encode; rides a new always-written, presence-guarded meta trailer with the features bitset (
ABI.md §4.2).shellcade-kit playhonors it locally. Host-side precedence: adminhost.heartbeat_ms> declaration > 50ms default.3. Rust crate parity (including a v2.5.0 gap)
v2.5.0's
rosterCap16→1024 + lazy baselines shipped Go-only — the Rust crate still silently droppedsendfor index ≥ 16. This PR brings the Rust crate to full parity:ROSTER_CAP1024, per-slot lazy baselines, allocated-only broadcast reconcile, both new meta fields, sentinel decode, and anRc-shared epoch roster cache. Golden vectors pin Go/Rust meta encodings byte-identical (trailer bytes cross-checked against the actual Go encoder).Also
GUIDE.md: new "Large rooms" authoring section — declare heartbeat + feature, render-on-change dirty tracking,Members()lifetime contract.AllocsPerRunceiling on the unchanged form; meta validation panics; Rust sentinel decode + trailer golden + lazy-reconcile contract.go test ./...andcargo testgreen.Sequencing: merge + tag v2.6.0 → engine PR pins it.
🤖 Generated with Claude Code