separate DMs and spectators

This commit is contained in:
Gavin McDonald
2025-04-14 14:22:06 -04:00
parent 4189e41da5
commit 424b8e0ec3
4 changed files with 59 additions and 21 deletions

View File

@@ -1,13 +1,17 @@
'use client';
import { useRouter } from 'next/navigation';
import generateID from '@/tools/simpleID';
import { socket } from '@/socket';
import { GameUpdate } from '@/types';
export default function Home() {
const router = useRouter();
const handleCreateGame = () => {
const id = generateID();
router.push(`/${id}`);
socket.emit('start');
socket.on('new-game', (game: GameUpdate) => {
router.push(`/${game.dmID}`);
});
};
return (

View File

@@ -1,33 +1,56 @@
import Deck from './TarokkaDeck';
import { GameState, GameUpdate, TarokkaGameCard } from '../types';
import Deck from '@/lib/TarokkaDeck';
import generateID from '@/tools/simpleID';
import { GameState, GameUpdate } from '@/types';
const deck = new Deck();
export default class GameStore {
private games: Map<string, GameState>;
private dms: Map<string, GameState>;
private spectators: Map<string, GameState>;
constructor() {
this.games = new Map();
this.dms = new Map();
this.spectators = new Map();
}
createGame(id: string): GameState {
if (this.games.has(id)) throw new Error(`Game ${id} already exists`);
createGameIDs() {
const dmID = generateID();
const spectatorID = generateID();
if (
this.dms.has(dmID) ||
this.dms.has(spectatorID) ||
this.spectators.has(dmID) ||
this.spectators.has(spectatorID)
) {
return this.createGameIDs();
}
return {
dmID,
spectatorID,
};
}
createGame(): GameState {
const { dmID, spectatorID } = this.createGameIDs();
const newGame: GameState = {
id,
dmID,
spectatorID,
players: new Set(),
cards: deck.getHand(),
lastUpdated: Date.now(),
};
this.games.set(id, newGame);
this.dms.set(dmID, newGame);
this.spectators.set(spectatorID, newGame);
return newGame;
}
joinGame(gameID: string, playerID: string): GameUpdate {
const game = this.games.get(gameID) || this.createGame(gameID);
const game = this.getGame(gameID) || this.createGame();
game.players.add(playerID);
game.lastUpdated = Date.now();
@@ -57,7 +80,7 @@ export default class GameStore {
}
getGame(gameID: string): GameState {
const game = this.games.get(gameID);
const game = this.dms.get(gameID) || this.spectators.get(gameID);
if (!game) throw new Error(`Game ${gameID} not found`);
@@ -65,12 +88,13 @@ export default class GameStore {
}
gameUpdate(game: GameState): GameUpdate {
const { id, cards } = game;
const { dmID, spectatorID, cards } = game;
return { id, cards };
return { dmID, spectatorID, cards };
}
deleteGame(gameID: string): void {
this.games.delete(gameID);
this.dms.delete(gameID);
this.spectators.delete(gameID);
}
}

View File

@@ -2,8 +2,8 @@ import next from 'next';
import { createServer } from 'http';
import { Server as SocketIOServer, type Socket } from 'socket.io';
import GameStore from './lib/GameStore';
import type { ClientUpdate } from './types';
import GameStore from '@/lib/GameStore';
import type { ClientUpdate } from '@/types';
const dev = process.env.NODE_ENV !== 'production';
const hostname = '0.0.0.0';
@@ -22,6 +22,14 @@ app.prepare().then(() => {
io.on('connection', (socket: Socket) => {
console.log(`Client connected: ${socket.id}`);
socket.on('start', () => {
const gameUpdate = gameStore.createGame();
console.log(`Socket ${socket.id} started game ${gameUpdate.dmID}`);
socket.emit('new-game', gameUpdate);
});
socket.on('join', (gameID) => {
socket.join(gameID);
const gameUpdate = gameStore.joinGame(gameID, socket.id);

View File

@@ -63,14 +63,16 @@ export type TarokkaCard = TarokkaBase | TarokkaHigh | TarokkaLow;
export type TarokkaGameCard = TarokkaGameBase | TarokkaGameHigh | TarokkaGameLow;
export interface GameState {
id: string;
dmID: string;
spectatorID: string;
players: Set<string>;
cards: TarokkaGameCard[];
lastUpdated: number;
}
export interface GameUpdate {
id: string;
dmID: string;
spectatorID: string;
cards: TarokkaGameCard[];
}