Skip to content

Mayur Reddy

Software Engineer

Menu

Projects / CyberRunner

CyberRunner

2025-2026

Browser FPS with 60 Hz server-owned movement and hits, plus ArenaForge, a level-design agent in the same runtime.

GitHub ↗Demo ↗

First-person CyberRunner match with the AR-1 visible in Shoot House Neon.

CyberRunner is a browser multiplayer first-person shooter. The server owns movement and hits. Clients predict locally so controls feel immediate, then reconcile when the server acknowledges an input.

ArenaForge lives in the same application. You draw an arena boundary, place starts, and give a brief. The agent edits a structured map, runs deterministic gameplay checks, and can launch the result in CyberRunner. Playing a saved map does not call a model.

Play: game.cyberrunnergame.dev. Guest play works.

What I built

  • Fixed 60 Hz server-authoritative RAPIER simulation for movement, hits, ammo, and match state.
  • Client prediction and snapshot reconciliation on a shared CharacterController.
  • 15-byte input_bin and 13-byte fire_bin command codecs.
  • Bounded tick-rewind hitscan (RTT/2 plus 1.5 ticks, capped at 250 ms).
  • Deathmatch and Search & Destroy, including spike plant and defuse.
  • ArenaForge: bounded map-edit tools, deterministic geometry/navigation/spawn/LOS checks, optional scripted playtest, and launch into the live room.
  • Recorded Design path that demonstrates the native loop without a model key.

How it works

Client 60 Hz input
  → local RAPIER prediction + 15-byte input_bin
  → server queue (max 24), one command per tick
  → authoritative RAPIER world
  → PlayerState + lastProcessedInputSeq
  → client restore / apply pose / replay leftovers

Firing uses fire_bin. Shot origin comes from rewind history. Aim is client-originated and sanitized. Shared movement, capsule, and map collision live in shared/.

ArenaForge writes GameplayMapDefinition maps that load into the same room.

Evidence

Local synthetic numbers from npm run benchmark on 2026-08-29 (Node v23.11.0, Windows, i9-14900KF):

Item Value
INPUT_CMD size 15 bytes
FIRE_CMD size 13 bytes
60 Hz input payload 900 B/s
Tick time, 1 / 4 / 8 capsules mean 0.017 / 0.054 / 0.151 ms

F3 in a match shows RTT, seq/ack, pending replay, and predicted vs server pose.

Historical ArenaForge evaluation: both designers solved simple repair cases in one edit. A harder interaction suite did not show the iterative designer winning overall (one-shot 88.9%, iterative 86.1%).

Limits

  • Single-region rooms. Default cap is 8 players.
  • Remotes use chase-latest lerp, not a delayed snapshot buffer.
  • Client prediction does not collide with other players.
  • Hitscan rewinds. Projectiles use current poses.
  • Live design is one active job per process. Saving personal maps needs Postgres and a signed-in profile.

Figures

Client and server netcode diagram from the CyberRunner repository.
Client and server netcode diagram from the CyberRunner repository.