194 lines
4.3 KiB
TypeScript
194 lines
4.3 KiB
TypeScript
/**
|
|
* Game-specific metadata types
|
|
* These extend the base Room/Session types with Settlers of Catan specific data
|
|
*/
|
|
|
|
import type { Player, Turn, Placements, DevelopmentCard } from "./types";
|
|
|
|
/**
|
|
* Game-specific session metadata
|
|
* This is stored in Session.metadata for each session
|
|
*/
|
|
export interface GameSessionMetadata {
|
|
// Player association
|
|
color?: string; // The color this session is playing as
|
|
player?: Player; // Reference to the player object
|
|
|
|
// Temporary resources (for trading, etc.)
|
|
resources?: number;
|
|
}
|
|
|
|
/**
|
|
* Game-specific room metadata
|
|
* This is stored in Room.metadata for the game room
|
|
*/
|
|
export interface GameRoomMetadata {
|
|
// Game data
|
|
developmentCards: DevelopmentCard[];
|
|
players: Record<string, Player>; // Keyed by color
|
|
unselected?: any[]; // Sessions without color selection
|
|
active?: number; // Number of active players
|
|
|
|
// Game state
|
|
rules?: any;
|
|
step?: number;
|
|
placements: Placements;
|
|
turn: Turn;
|
|
|
|
// Board setup
|
|
pipOrder?: number[];
|
|
tileOrder?: number[];
|
|
borderOrder?: number[];
|
|
tiles?: any[];
|
|
pips?: any[];
|
|
borders?: any[];
|
|
|
|
// Game flow
|
|
dice?: number[];
|
|
chat?: any[];
|
|
activities?: any[];
|
|
playerOrder?: string[];
|
|
direction?: string;
|
|
turns?: number;
|
|
|
|
// Game stats
|
|
robber?: number;
|
|
robberName?: string;
|
|
longestRoad?: string | false;
|
|
longestRoadLength?: number;
|
|
largestArmy?: string | false;
|
|
largestArmySize?: number;
|
|
mostPorts?: string | false;
|
|
mostDeveloped?: string | false;
|
|
|
|
// Debug
|
|
debug?: boolean;
|
|
signature?: string;
|
|
animationSeeds?: number[];
|
|
|
|
// Timers
|
|
turnTimer?: any;
|
|
}
|
|
|
|
/**
|
|
* Helper type for a complete game room
|
|
*/
|
|
export type GameRoom = {
|
|
id: string;
|
|
name: string;
|
|
sessions: Record<string, GameSession>;
|
|
state: string;
|
|
created: number;
|
|
lastActivity: number;
|
|
private?: boolean;
|
|
metadata: GameRoomMetadata;
|
|
};
|
|
|
|
/**
|
|
* Helper type for a game session
|
|
*/
|
|
export type GameSession = {
|
|
id: string;
|
|
userId?: number;
|
|
name: string | null;
|
|
ws?: any;
|
|
live: boolean;
|
|
lastActive: number;
|
|
keepAlive?: any;
|
|
connected: boolean;
|
|
has_media: boolean;
|
|
protected?: boolean;
|
|
bot_run_id?: string | null;
|
|
bot_provider_id?: string | null;
|
|
bot_instance_id?: string | null;
|
|
_initialSnapshotSent?: boolean;
|
|
_getBatch?: { fields: Set<string>; timer?: any };
|
|
_pendingMessage?: any;
|
|
_pendingTimeout?: any;
|
|
metadata?: GameSessionMetadata;
|
|
};
|
|
|
|
/**
|
|
* Migration helpers to convert between old and new formats
|
|
*/
|
|
|
|
/**
|
|
* Convert old Session to new format
|
|
*/
|
|
export function migrateSessionToNewFormat(oldSession: any): GameSession {
|
|
const { color, player, resources, ...baseFields } = oldSession;
|
|
|
|
return {
|
|
...baseFields,
|
|
has_media: baseFields.has_media ?? true,
|
|
name: baseFields.name ?? null,
|
|
live: baseFields.live ?? false,
|
|
connected: baseFields.connected ?? false,
|
|
lastActive: baseFields.lastActive ?? Date.now(),
|
|
metadata: {
|
|
color,
|
|
player,
|
|
resources,
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Convert new Session to old format (for backward compatibility)
|
|
*/
|
|
export function migrateSessionToOldFormat(newSession: GameSession): any {
|
|
const { metadata, ...baseFields } = newSession;
|
|
|
|
return {
|
|
...baseFields,
|
|
color: metadata?.color,
|
|
player: metadata?.player,
|
|
resources: metadata?.resources,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Convert old Game to new Room format
|
|
*/
|
|
export function migrateGameToRoomFormat(oldGame: any): GameRoom {
|
|
const { sessions, id, ...gameFields } = oldGame;
|
|
|
|
// Convert sessions
|
|
const newSessions: Record<string, GameSession> = {};
|
|
for (const sessionId in sessions) {
|
|
newSessions[sessionId] = migrateSessionToNewFormat(sessions[sessionId]);
|
|
}
|
|
|
|
return {
|
|
id: oldGame.id,
|
|
name: oldGame.id, // Game ID is the room name
|
|
sessions: newSessions,
|
|
state: oldGame.state || "lobby",
|
|
created: Date.now(),
|
|
lastActivity: Date.now(),
|
|
private: false,
|
|
metadata: gameFields,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Convert new Room to old Game format (for backward compatibility)
|
|
*/
|
|
export function migrateRoomToGameFormat(room: GameRoom): any {
|
|
const { metadata, sessions, ...roomFields } = room;
|
|
|
|
// Convert sessions back
|
|
const oldSessions: Record<string, any> = {};
|
|
for (const sessionId in sessions) {
|
|
if (sessions[sessionId]) {
|
|
oldSessions[sessionId] = migrateSessionToOldFormat(sessions[sessionId]);
|
|
}
|
|
}
|
|
|
|
return {
|
|
...roomFields,
|
|
...metadata,
|
|
sessions: oldSessions,
|
|
};
|
|
}
|