Authoritative arena, bandwidth reduction, and staged low-latency hosting
See WebRTC private-match plan for a staged connectivity probe and three-human reliable-channel experiment with rotating hosts, precise-turn measurements, and a comparison with dedicated-server transports. This proposal does not supersede the public hosting plan below or authorize implementation.
Adopt the staged migration below, based on the hosting proposal review. Keep the static client on GitHub Pages and AI services on the existing Cloudflare Worker. Target one Google Cloud VM for the authoritative public arena, first over WebSockets and then with WebTransport plus WebSocket fallback. Preserve the shared JavaScript simulation, public queue, AI vacancy filling and current gameplay. This is the implementation plan, not authorization to purchase infrastructure or publish a deployment.
The current production arena uses the Cloudflare Durable Object. Protocol 2 bandwidth reductions are in the October 14 release: the compatible Worker and matching static client are deployed and production browser checks passed. The measured 93.2% reduction is a five-second twelve-cycle benchmark, not evidence of lower production latency. The historical browser-host/WebRTC proposal later on this page is superseded by this plan.
The proposed $25–60/month is a provisional base infrastructure budget, not a total-cost guarantee. Estimate VM, IPv4, disk, outbound bandwidth, logging and monitoring from measured player/spectator hours before provisioning. See Compute pricing and network pricing. No assumed future Cloudflare UDP release is a dependency.
Keep the same authoritative room and simulation for both transports. Prove a maintained server implementation can host the shared JavaScript authority before committing to a transport library. Negotiate protocol capabilities and fall back to WebSockets when WebTransport is unsupported or UDP is blocked.
| Information | Delivery requirement |
|---|---|
| Replaceable motion state | Unreliable datagrams, independently decodable or based on an explicitly acknowledged baseline; discard stale updates |
| Turn/control inputs | Sequenced, bounded repetition and acknowledgments; retry until acknowledged or explicitly expired/rejected |
| Trail creation/removal | Reliable sequenced events, or repeated acknowledged events with equivalent recovery guarantees |
| Join, queue, round boundaries, confirmed deaths and scores | Reliable stream with round/event IDs and duplicate protection |
| Initial state and repairs | Reliable complete snapshots, with event/baseline IDs to coordinate subsequent updates |
WebTransport provides unreliable datagrams and reliable streams; it does not remove geographic delay. Keep fallback for older browsers and blocked UDP. See WebTransport datagrams. The current Workers protocol documentation and Containers architecture do not provide the direct inbound UDP game-server endpoint this plan needs; HTTP/3 support alone is not a WebTransport service.
Planning validation: this update documents the selected architecture and acceptance gates only. VM, WebTransport, network-impairment and migration checks above remain unrun. Regenerate the HTML and indexes with node docs/colvmn/static-gen.js docs.
The user-selected design is one public, server-authoritative arena, reached through LIGHT CYCLES MULTIPLAYER. Six, nine or twelve cycles compete, with at most three cycles per team. Humans occupy available seats and AI fills the rest; additional humans spectate in a FIFO waiting queue. Surviving humans keep their seats, eliminated humans rejoin the back of the queue, and disconnects release seats. Teams are randomized between matches, with two, three or four teams; enough teams are added to seat up to twelve humans. Countdown expansion preserves the scheduled start time.
The local Vite server hosts the room at /api/multiplayer. Production support is prepared as one Cloudflare Durable Object named public-arena-v1, using the existing Worker and MULTIPLAYER_ARENA binding. The authoritative Worker is deployed and a production-origin WebSocket check confirms advancing snapshots and the three-cycle team cap. The static client has also been published; the protocol 2 client update was published in the October 14 release. Run npm run dev, choose the multiplayer menu, and open another browser window to join the same room. Single-player does not load the multiplayer client or start a multiplayer network loop.
The referee runs the shared simulation at 120 Hz and sends trail-delta snapshots at 20 Hz. The deployed baseline schedules sequenced inputs eight ticks ahead (about 67 ms). The October 14 local follow-up below removes that lead and applies accepted inputs on the next authority tick, retaining bounded timestamp acceptance. Clients extrapolate motion and predict their pending turns; collision and elimination remain authoritative. There is no rollback yet. A late command takes effect on a future server tick rather than rewriting a collision. This removes browser-host authority advantage but does not make differing network latency equal.
Human cycles carry a thick diagonal stripe, first half black and second half white, on the colored shell. Their roster circles mirror it; your circle has an extra outline. Eliminated circles retain their team outline with transparent interiors. Custom stripe patterns are a possible later addition.
The room stops when empty. Active rounds are bounded to three minutes or 2,048 trail segments, connections to 64, input messages to 512 bytes and 80 per second, with idle and slow-connection limits. An active simulation keeps its server instance awake: exact hosting cost needs measurement. No paid service was purchased. The deployment flag MULTIPLAYER_ENABLED can disable access.
Multiplayer does not pause when the window loses focus; held controls clear and input resumes immediately on focus. Escape still opens the return-home confirmation. The controls hint sits below multiplayer status.
The earlier browser-host proposal below is retained as an architecture comparison, not the selected implementation. Its private rooms, WebRTC and rollback milestones have not been implemented. Pricing references in that proposal were checked October 13, 2026.
The arena currently simulates at 120 Hz and cycles normally travel 38.4 meters per second. One simulation step moves a cycle 0.32 meters. A 50 ms delay means 1.92 meters of travel; 100 ms means 3.84 meters, longer than the 3.6-meter bike. Network delay cannot simply be hidden behind smooth animation when a new wall decides whether someone lives.
Those distances use actual elapsed delay, not automatically the displayed ping. Round-trip time includes both directions; half the ping only approximates one-way delay on a symmetric connection. Jitter buffers and input scheduling add more time. Rendering at 60 fps does not make a delayed turn timely.
Local steering should respond immediately through prediction. Remote steering will sometimes need correction. The difficult case is a late turn that creates a wall across another player's already-predicted path. Reconciliation must include trail geometry and collision outcomes, not just vehicle positions.
The remaining architecture comparison, prototype, budget and acceptance sections describe the earlier browser-host option. They are retained for reference and are not the selected migration steps.
| Approach | Strength | Main cost or limitation |
|---|---|---|
| Browser host with WebRTC | Minimal server simulation cost; direct connection when possible | Host advantage, host cheating and suspension; TURN sometimes required |
| Authoritative server with WebSockets | Shared referee and simpler connection setup | Active server cost; delayed reliable packets can hold up newer data |
| Deterministic lockstep between peers | Very small input messages | Waiting for inputs delays everyone; exact reproducibility required |
| Peer rollback without a single referee | Immediate local prediction | Harder dispute handling and synchronized trail/death corrections |
Start with host authority, not full peer consensus. The host simulates all players and bots, accepts validated inputs, and broadcasts authoritative snapshots and events. Clients predict their own motion and reconcile against those snapshots. WebRTC is the transport; it does not itself solve fairness or synchronization.
Lockstep needs identical simulation results for identical inputs, and waiting for missing inputs can cause stalls. A fixed timestep alone does not prove determinism across browsers. See Glenn Fiedler's deterministic lockstep explanation.
Use a reliable control channel for room state, starts and confirmed outcomes. A separate channel can carry disposable latest-state updates. Critical turns still need delivery or repetition and acknowledgments even if their transport is unreliable. Avoid resending the entire growing wall history each frame: send sequenced trail events, periodic checksums and occasional recovery snapshots.
The first prototype should end the room cleanly if its host leaves or suspends. Host migration, spectators, public matchmaking and competitive anti-cheat can wait. A malicious browser host remains trusted in this design; private casual rooms are the appropriate initial scope. Direct peer connections can expose network addresses to peers; relay-only mode trades that exposure for relay traffic.
Use an isolated room/signaling endpoint alongside the existing Worker, with short room expiry and limited joins. Keep only ephemeral room metadata; do not persist every game tick. Issue short-lived TURN credentials on the server, never a permanent service key in the client. Rate-limit room creation and cap simultaneous rooms and relay usage independently of the existing AI endpoints.
Cloudflare lists TURN at $0.05 per outbound GB with a 1,000 GB free allowance; STUN is free. Verify allowance scope and account terms before enabling it. At a hypothetical total metered relay rate of 20 KB/s per room, one room-hour is about 0.072 GB. Actual traffic depends on players, packet overhead and how many connections require relaying. TURN pricing FAQ.
For an authoritative Durable Object alternative, the paid plan includes 400,000 GB-seconds monthly and one million requests. Active objects are charged at 0.128 GB; incoming WebSocket messages use a 20:1 billing ratio. Extra duration is $12.50 per million GB-seconds, rounded up; the paid baseline is $5 monthly. An active simulation must not be budgeted as an idle hibernating lobby. Durable Object pricing.
Illustrative calculation: 100 room-hours consume 46,080 GB-seconds. Four clients each sending 30 messages/second produce 2.16 million billable request equivalents over those hours. This excludes joins, other Worker traffic, storage and existing account usage. These are planning calculations, not measured game costs. A small fixed-price server is another option if sustained usage grows, but adds maintenance and regional deployment work.
The cheapest practical first version should mostly pay for signaling and occasional relay traffic, with simulation on the host. Set application admission limits before any public launch; billing alerts alone do not enforce a spending ceiling.
Expand to four humans only after two-player cutoffs feel convincing. The goal is satisfying casual play at low cost, not a promise that intercontinental close-contact racing can feel identical to local play.
Protocol 2 transmits only presentation state and changes to that state. Coordinates are rounded to 0.0001 grid cells (0.48 mm); authority and collision calculations remain full precision. AI planning state, collision grids and render history stay server-side. The initial snapshot and new rounds are complete; later snapshots carry cycle/trail field patches, a baseline tick, and changed roster/crash data. Baseline mismatch requests a complete repair. Protocol 1 remains available for older cached clients; deploy the Worker before the client.
node scripts/measure-multiplayer-bandwidth.mjs compares both formats on the same five-second simulation. With twelve cycles, protocol 1 averages 197,499 bytes/sec per player and protocol 2 averages 13,360 bytes/sec, a 93.2% reduction before compression. Six cycles with one human drop 88.5%. Event-driven updates after applied human control changes supplement the usual 20 Hz updates. These are bandwidth results, not a measured reduction in live latency.
WebTransport provides unreliable datagrams suited to replaceable position updates, with reliable streams for turns and game events. WebRTC data channels can also be unordered with limited retransmission. Both require a compatible peer/server; they are not raw UDP sockets exposed to browser JavaScript. The current Cloudflare Workers protocol list documents HTTP, WebSockets and TCP interfaces, but no direct WebTransport or WebRTC game-server API. HTTP/3 support alone does not supply the WebTransport session/datagram API. A future change would need a suitable separately hosted authoritative server or transport gateway, reliable event delivery, obsolete-update dropping, and WebSocket fallback. It may reduce stalls from retransmission under packet loss; it will not remove propagation latency. No new hosting has been provisioned.
Straight-line choppiness can occur without low rendering FPS: the old client restarted its extrapolation clock at each snapshot arrival, converting network jitter into position corrections. It also applied the local input lead to opponents whose future controls were unknown. Remote presentation now uses a continuous clock and a 75 ms snapshot buffer, interpolating through confirmed trail corners while keeping bike and trail endpoints together. The clock adjusts its rate within 10% to maintain the buffer and holds at the latest confirmed pose if updates stop. Local prediction remains immediate on its existing timeline; authoritative deaths and HUD state are not delayed.
The jitter regression at 144 Hz reduces worst normal-speed straight-line frame-step error from 1.344 m to 0.0267 m under the tested 15–50 ms delivery delays. A 50 ms buffer ran dry in that test. Jittered two-client Chrome checks and the build pass. These results do not establish real-player fairness or subjective smoothness: the remote presentation buffer adds delay, and long network stalls can still hold motion. Deployed October 14: TRON b9b1948, dekorte.com c5a52e0, Pages run 38608501930. All 525 unit tests and the production build pass. Production Chrome confirmed the new playback code, 53 compact snapshots and solo restart with no page errors; the existing server is unchanged.
The next local change removes the fixed eight-tick lead for local presentation and input packets. Input timestamps still establish freshness, but no longer delay an accepted command: the server applies it on its next 120 Hz tick. Clients record a fractional keypress time privately, predict the turn at their displayed position immediately, and replay it until acknowledged. The preceding trail ends at the predicted corner. Remote cycles retain their separate 75 ms playback buffer.
With 1.8 m of clearance to the existing arena wall's collision boundary, tests at normal speed (38.4 m/s) and turbo (96 m/s) survive zero/two-tick input transit under next-tick handling, whereas the old eight-tick schedule crashes. Two ticks of transit move the accepted turn 0.64/1.6 m from the keypress position. Six ticks of transit (50 ms) is too late at that clearance for either approach. All 528 unit tests, production build and Worker dry run pass. These are controlled simulation results, not a guarantee of precise turning at arbitrary network latency.
No collision rollback or provisional death system is included. Inputs received after confirmed impact cannot restore the player. This follow-up requires both a server and client deployment; it is currently local only.