Developer docs
Everything you need to take one TypeScript module from an idea to staked, settled matches on Robinhood Chain.
01 — The model
A FORGE game is a single pure-TypeScript object — a GameModule. It owns rules, state and scoring. It does not know about sockets, wallets, rendering or the chain. The engine supplies all of that: matchmaking and custom invite lobbies, deterministic room execution, per-player state redaction, scripted-bot fill, N-player stake escrow on Robinhood Chain, and split settlement with a hard-capped rake. You bring any renderer — three.js, canvas, plain DOM — and paint the frames the relay streams.
Because rooms are deterministic (fixed steps, seeded RNG, ordered inputs), the same module runs authoritatively on the relay and instantly in a browser tab. The playground literally runs the shipped Tap Duel module client-side.
02 — Quickstart
# 1. run the relay (rh-game-engine-backend) npm install && npm run dev # relay on :4500 # 2. verify everything npm run smoke # determinism + full duel + 3p lobby npm run test:escrow # 32-check EVM audit of ForgeEscrow # 3. write your game # src/templates/my-game.ts — export a GameModule # register it in src/templates/index.ts — done: # matchmaking, lobbies, bots, stakes and settlement now apply to it.
03 — The module API
export const myGame: GameModule<State, Input> = {
id: "my-game", name: "MY GAME", blurb: "…",
minPlayers: 2, maxPlayers: 4,
tickRate: 20, // fixed sim steps per second
snapshotRate: 12, // frames streamed to clients
maxDurationMs: 120_000,
setup(ctx) { /* initial state — ctx.random is the seeded stream */ },
onInput(state, player, input, ctx) {
/* validate + apply. This IS your rules engine — reject anything
illegal here and cheating is impossible by construction. */
},
tick(state, ctx) { /* advance one fixed step (ctx.dt seconds) */ },
view(state, player) { /* optional: hide what this player can't see */ },
result(state) { /* null while live; else winners + splitBps
summing 10000 — the engine pays this table */ },
};Three shipped templates cover the genre space: Tap Duel (real-time reactions), Grid Battle (turn-based tactics) and Score Rush (2–4 player contested scramble). Copy the closest one.
04 — Client SDK
import { ForgeClient } from "rh-game-engine-backend/src/client";
const forge = new ForgeClient("https://your-relay.example");
forge.on("found", (m) => showLobby(m));
forge.on("frame", (f) => render(f.view, f.events)); // any renderer
forge.on("finish", (p) => showResult(p.result));
forge.queue("my-game", "free"); // or a staked tier + address
button.onclick = () => forge.sendInput({ kind: "tap" });
// custom games: forge.createLobby(...) → share code → forge.joinLobby(code)05 — Money protocol
Staked matches run through ForgeEscrow.sol — a single non-upgradeable contract built on OpenZeppelin v5, generalizing the audited two-player escrow that powers RICOCHET:
referee openMatch(id, players[2..8], stake)
players deposit(id) // one tx each, exact stake
→ Funded → room goes live
module reports result → referee settle(id, winners[], splitsBps[])
→ pot − rake paid by the split table (dust-exact), rake accrues
draws → cancelMatch → every deposit refunded
relay dead? → players reclaim() after timeout windows;
the FIRST funded reclaim permanently blocks settlement —
a pot can never be double-spent.Owner powers stop at: rotate referee, set rake for future matches (hard cap 10%), pause new activity, sweep accrued rake. The owner can never touch player stakes; pausing never blocks exits; hostile winners fall back to pull-payments. All of it is executed against the compiled bytecode in npm run test:escrow — 32 checks including solvency.
06 — Determinism
1. no Math.random() → use ctx.random (seeded per room) 2. no Date.now() → use ctx.now (simulated milliseconds) 3. mutate state only inside setup / onInput / tick same seed + same inputs = same result, everywhere. That property is what makes replays, desync detection and browser-identical local play possible — the smoke test asserts it.
Fastest way to feel the engine: play the module it ships.
Play the engine