import { PredictedEngine } from "./client.js"; import { AuthoritativeEngine, type ServerEngineOptions } from "./server.js"; import type { GameDefinition } from "./types.js"; export interface DefinedGame extends GameDefinition { createServer(options?: ServerEngineOptions): AuthoritativeEngine; createClient(): PredictedEngine; } export function defineGame( definition: GameDefinition, ): DefinedGame { if (!Number.isInteger(definition.tickRateHz) || definition.tickRateHz <= 0) { throw new RangeError("tickRateHz must be a positive integer"); } if ( !Number.isInteger(definition.snapshotRateHz) || definition.snapshotRateHz <= 0 || definition.snapshotRateHz > definition.tickRateHz || definition.tickRateHz % definition.snapshotRateHz !== 0 ) { throw new RangeError( "snapshotRateHz must be a positive divisor of tickRateHz", ); } return Object.freeze({ ...definition, createServer(options?: ServerEngineOptions) { return new AuthoritativeEngine(definition, options); }, createClient() { return new PredictedEngine(definition); }, }); }