feat(games): add room types and game WS message schemas
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
54
api/src/games/types.ts
Normal file
54
api/src/games/types.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
// --- Room types ---
|
||||||
|
|
||||||
|
export interface Room {
|
||||||
|
id: string;
|
||||||
|
gameSlug: string;
|
||||||
|
host: string;
|
||||||
|
players: string[];
|
||||||
|
spectators: Set<string>;
|
||||||
|
state: unknown;
|
||||||
|
status: "waiting" | "playing" | "finished";
|
||||||
|
createdAt: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RoomSummary {
|
||||||
|
id: string;
|
||||||
|
gameSlug: string;
|
||||||
|
gameName: string;
|
||||||
|
host: string;
|
||||||
|
playerCount: number;
|
||||||
|
maxPlayers: number;
|
||||||
|
spectatorCount: number;
|
||||||
|
status: "waiting" | "playing" | "finished";
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PlayerInfo {
|
||||||
|
discordId: string;
|
||||||
|
username: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Client → Server messages ---
|
||||||
|
|
||||||
|
export const GameWsClientSchema = z.discriminatedUnion("type", [
|
||||||
|
z.object({ type: z.literal("CREATE_ROOM"), gameType: z.string() }),
|
||||||
|
z.object({ type: z.literal("JOIN_ROOM"), roomId: z.string(), as: z.enum(["player", "spectator"]) }),
|
||||||
|
z.object({ type: z.literal("LEAVE_ROOM"), roomId: z.string() }),
|
||||||
|
z.object({ type: z.literal("GAME_ACTION"), roomId: z.string(), action: z.record(z.unknown()) }),
|
||||||
|
]);
|
||||||
|
|
||||||
|
export type GameWsClientMessage = z.infer<typeof GameWsClientSchema>;
|
||||||
|
|
||||||
|
// --- Server → Client messages ---
|
||||||
|
|
||||||
|
export type GameWsServerMessage =
|
||||||
|
| { type: "ROOM_LIST_UPDATE"; rooms: RoomSummary[] }
|
||||||
|
| { type: "GAME_STATE"; roomId: string; state: unknown }
|
||||||
|
| { type: "GAME_UPDATE"; roomId: string; state: unknown }
|
||||||
|
| { type: "PLAYER_JOINED"; roomId: string; player: PlayerInfo; as: "player" | "spectator" }
|
||||||
|
| { type: "PLAYER_LEFT"; roomId: string; playerId: string }
|
||||||
|
| { type: "GAME_STARTED"; roomId: string; state: unknown }
|
||||||
|
| { type: "GAME_ENDED"; roomId: string; winner: string | null; reason: string }
|
||||||
|
| { type: "ROOM_CREATED"; roomId: string; gameSlug: string }
|
||||||
|
| { type: "ERROR"; message: string };
|
||||||
@@ -110,6 +110,11 @@ export const WsMessageSchema = z.discriminatedUnion("type", [
|
|||||||
z.object({ type: z.literal("PONG") }),
|
z.object({ type: z.literal("PONG") }),
|
||||||
z.object({ type: z.literal("STATS_UPDATE"), data: DashboardStatsSchema }),
|
z.object({ type: z.literal("STATS_UPDATE"), data: DashboardStatsSchema }),
|
||||||
z.object({ type: z.literal("NEW_EVENT"), data: RecentEventSchema }),
|
z.object({ type: z.literal("NEW_EVENT"), data: RecentEventSchema }),
|
||||||
|
// Game messages (client → server)
|
||||||
|
z.object({ type: z.literal("CREATE_ROOM"), gameType: z.string() }),
|
||||||
|
z.object({ type: z.literal("JOIN_ROOM"), roomId: z.string(), as: z.enum(["player", "spectator"]) }),
|
||||||
|
z.object({ type: z.literal("LEAVE_ROOM"), roomId: z.string() }),
|
||||||
|
z.object({ type: z.literal("GAME_ACTION"), roomId: z.string(), action: z.record(z.unknown()) }),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export type WsMessage = z.infer<typeof WsMessageSchema>;
|
export type WsMessage = z.infer<typeof WsMessageSchema>;
|
||||||
|
|||||||
Reference in New Issue
Block a user