- TypeScript 93.6%
- JavaScript 4.8%
- HTML 1.6%
| dist | ||
| scripts | ||
| src | ||
| .gitignore | ||
| index.html | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
| tsconfig.tsbuildinfo | ||
| vite.config.ts | ||
Bombo — P2P Bomberman
A serverless, P2P Bomberman-style game that uses:
- WebRTC DataChannels for low-latency real-time gameplay
- Pubsub-style relay for lobby discovery and WebRTC signaling (minimal bootstrap)
- Host-authoritative game state: one peer simulates, others send inputs and receive state
No long-lived game servers: you run a tiny relay (or use a public one), and players connect directly via WebRTC for the actual game.
Quick start
-
Start the relay (one terminal):
npm run relayListens on
ws://localhost:9090by default. SetPORTto change it. -
Start the app (another terminal):
npm run dev -
Open two browser tabs at the dev server URL:
- In one tab: click Host game
- In the other: pick the game from the list and click Join
- Play: WASD / Arrows move, Space places a bomb
Architecture
-
Relay server (
scripts/relay-server.mjs): WebSocket server that broadcasts every message to all connected clients. Used only for:- Lobby: host publishes “game open” with game id and peer id; clients subscribe and see the list.
- Signaling: SDP offer/answer and ICE candidates for WebRTC, so peers can open a direct DataChannel.
-
Game traffic goes over a WebRTC DataChannel (peer-to-peer), not through the relay.
-
Gameplay: Host runs the game loop, applies inputs from all players, and sends state snapshots over the DataChannel. Clients send inputs and render received state.
Scripts
npm run dev— Vite dev servernpm run build— Production buildnpm run preview— Preview production buildnpm run relay— Start WebSocket relay (lobby + signaling)npm run bootstrap— Start libp2p bootstrap server (optional; requires compatible libp2p stack)
Env (Vite)
VITE_BOOTSTRAP_WS— WebSocket URL for relay (default:ws://localhost:9090)
Optional: libp2p
The app can use libp2p + GossipSub instead of the relay for discovery and signaling (same WebRTC game channel). To do that you’d need:
- A running libp2p bootstrap node (e.g.
npm run bootstrapafter fixing the current bootstrap script’s deps). - Build/run with libp2p support (e.g. set
VITE_USE_RELAY=falseand resolve the current@libp2p/utils/pipeexport issue in the libp2p stack).
The relay mode is the default so the game works out of the box with minimal setup.