Room file API

@irtio/room defines the authoritative half of your game. A room file exports a single defineRoom(schema, handlers).

Signature

function defineRoom<S>(schema: S, handlers: RoomHandlers<S>): Room<S>;

interface RoomHandlers<S> {
  onJoin?(state: State<S>, ctx: Ctx): void;
  onLeave?(state: State<S>, ctx: Ctx): void;
  validate?: { [entity: string]: (prev, next, ctx) => Next | void };
  rpc?: { [name: string]: (state, args, ctx) => unknown };
  tick?(state: State<S>, dt: number, ctx: Ctx): void;
}

Handlers

HandlerRunsUse for
onJoin / onLeaveon membership changecreate/remove entities
validate.<entity>before a client write is broadcastclamp or reject
rpc.<name>when a client calls itarbitrated actions
tickfixed rate on the servercontinuous simulation

The context object

interface Ctx {
  clientId: string;       // caller / joiner
  meta: Record<string, unknown>;
  env: Record<string, string>;   // secrets & config, server-only
  now: number;            // deterministic clock (use instead of Date.now)
  random(): number;       // seeded RNG (use instead of Math.random)
  kick(clientId: string, reason?: string): void;
  broadcast(event: string, payload: unknown): void;
}

Always read time from ctx.now and randomness from ctx.random() — that’s what makes simulated-player tests deterministic.

Ownership helpers

import { SERVER } from '@irtio/room';

state.match = { phase: 'lobby', owner: SERVER };   // server-owned
state.pieces[id].owner = ctx.clientId;             // hand to a client

Next steps

Placeholder reference.