75 lines
2.1 KiB
JavaScript
75 lines
2.1 KiB
JavaScript
import crypto from 'node:crypto';
|
|
import { getGame } from './gameRegistry.js';
|
|
|
|
export class LobbyManager {
|
|
constructor() {
|
|
this.rooms = new Map();
|
|
}
|
|
|
|
list(gameSlug) {
|
|
return [...this.rooms.values()]
|
|
.filter((r) => !gameSlug || r.gameSlug === gameSlug)
|
|
.map((r) => this.summary(r));
|
|
}
|
|
|
|
summary(room) {
|
|
return {
|
|
id: room.id,
|
|
gameSlug: room.gameSlug,
|
|
name: room.name,
|
|
hostId: room.hostId,
|
|
players: room.players.map((p) => ({ id: p.userId, username: p.username, seat: p.seat })),
|
|
maxPlayers: room.maxPlayers,
|
|
status: room.status,
|
|
};
|
|
}
|
|
|
|
create({ gameSlug, hostUser, name }) {
|
|
const game = getGame(gameSlug);
|
|
if (!game) throw new Error(`Unknown game: ${gameSlug}`);
|
|
if (!game.supportsMultiplayer) throw new Error(`${game.name} is not multiplayer.`);
|
|
const id = crypto.randomBytes(6).toString('hex');
|
|
const room = {
|
|
id,
|
|
gameSlug,
|
|
name: name ?? `${hostUser.username}'s table`,
|
|
hostId: hostUser.id,
|
|
players: [{ userId: hostUser.id, username: hostUser.username, seat: 0 }],
|
|
maxPlayers: game.maxPlayers,
|
|
status: 'waiting',
|
|
};
|
|
this.rooms.set(id, room);
|
|
return room;
|
|
}
|
|
|
|
join(roomId, user) {
|
|
const room = this.rooms.get(roomId);
|
|
if (!room) throw new Error('Room not found.');
|
|
if (room.players.some((p) => p.userId === user.id)) return room;
|
|
if (room.players.length >= room.maxPlayers) throw new Error('Room is full.');
|
|
const usedSeats = new Set(room.players.map((p) => p.seat));
|
|
let seat = 0;
|
|
while (usedSeats.has(seat)) seat += 1;
|
|
room.players.push({ userId: user.id, username: user.username, seat });
|
|
return room;
|
|
}
|
|
|
|
leave(roomId, userId) {
|
|
const room = this.rooms.get(roomId);
|
|
if (!room) return null;
|
|
room.players = room.players.filter((p) => p.userId !== userId);
|
|
if (!room.players.length) {
|
|
this.rooms.delete(roomId);
|
|
return null;
|
|
}
|
|
if (room.hostId === userId) room.hostId = room.players[0].userId;
|
|
return room;
|
|
}
|
|
|
|
get(roomId) {
|
|
return this.rooms.get(roomId) ?? null;
|
|
}
|
|
}
|
|
|
|
export const lobby = new LobbyManager();
|