feat(games): add GamePlugin interface and registry

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
syntaxbullet
2026-04-02 13:22:48 +02:00
parent 29b6153777
commit a5478dce2b
2 changed files with 41 additions and 0 deletions

18
shared/games/registry.ts Normal file
View File

@@ -0,0 +1,18 @@
import type { GamePlugin } from "./types";
const games = new Map<string, GamePlugin>();
export const gameRegistry = {
register(plugin: GamePlugin) {
if (games.has(plugin.slug)) {
throw new Error(`Game "${plugin.slug}" is already registered`);
}
games.set(plugin.slug, plugin);
},
get(slug: string): GamePlugin | undefined {
return games.get(slug);
},
list(): GamePlugin[] {
return Array.from(games.values());
},
};

23
shared/games/types.ts Normal file
View File

@@ -0,0 +1,23 @@
export interface GamePlugin<TState = unknown, TAction = unknown> {
slug: string;
name: string;
minPlayers: number;
maxPlayers: number;
createInitialState(players: string[]): TState;
handleAction(state: TState, action: TAction, playerId: string): GameResult<TState>;
getPlayerView(state: TState, playerId: string): unknown;
getSpectatorView(state: TState): unknown;
isGameOver?(state: TState): GameOverResult | null;
onPlayerDisconnect?(state: TState, playerId: string): TState;
}
export type GameResult<TState> =
| { ok: true; state: TState }
| { ok: false; error: string };
export type GameOverResult = {
winner: string | null;
reason: string;
};