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

View File

@@ -1,33 +1,56 @@
import Deck from './TarokkaDeck'; import Deck from '@/lib/TarokkaDeck';
import generateID from '@/tools/simpleID';
import { GameState, GameUpdate, TarokkaGameCard } from '../types'; import { GameState, GameUpdate } from '@/types';
const deck = new Deck(); const deck = new Deck();
export default class GameStore { export default class GameStore {
private games: Map<string, GameState>; private dms: Map<string, GameState>;
private spectators: Map<string, GameState>;
constructor() { constructor() {
this.games = new Map(); this.dms = new Map();
this.spectators = new Map();
} }
createGame(id: string): GameState { createGameIDs() {
if (this.games.has(id)) throw new Error(`Game ${id} already exists`); 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 = { const newGame: GameState = {
id, dmID,
spectatorID,
players: new Set(), players: new Set(),
cards: deck.getHand(), cards: deck.getHand(),
lastUpdated: Date.now(), lastUpdated: Date.now(),
}; };
this.games.set(id, newGame); this.dms.set(dmID, newGame);
this.spectators.set(spectatorID, newGame);
return newGame; return newGame;
} }
joinGame(gameID: string, playerID: string): GameUpdate { 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.players.add(playerID);
game.lastUpdated = Date.now(); game.lastUpdated = Date.now();
@@ -57,7 +80,7 @@ export default class GameStore {
} }
getGame(gameID: string): GameState { 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`); if (!game) throw new Error(`Game ${gameID} not found`);
@@ -65,12 +88,13 @@ export default class GameStore {
} }
gameUpdate(game: GameState): GameUpdate { gameUpdate(game: GameState): GameUpdate {
const { id, cards } = game; const { dmID, spectatorID, cards } = game;
return { id, cards }; return { dmID, spectatorID, cards };
} }
deleteGame(gameID: string): void { 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 { createServer } from 'http';
import { Server as SocketIOServer, type Socket } from 'socket.io'; import { Server as SocketIOServer, type Socket } from 'socket.io';
import GameStore from './lib/GameStore'; import GameStore from '@/lib/GameStore';
import type { ClientUpdate } from './types'; import type { ClientUpdate } from '@/types';
const dev = process.env.NODE_ENV !== 'production'; const dev = process.env.NODE_ENV !== 'production';
const hostname = '0.0.0.0'; const hostname = '0.0.0.0';
@@ -22,6 +22,14 @@ app.prepare().then(() => {
io.on('connection', (socket: Socket) => { io.on('connection', (socket: Socket) => {
console.log(`Client connected: ${socket.id}`); 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.on('join', (gameID) => {
socket.join(gameID); socket.join(gameID);
const gameUpdate = gameStore.joinGame(gameID, socket.id); 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 type TarokkaGameCard = TarokkaGameBase | TarokkaGameHigh | TarokkaGameLow;
export interface GameState { export interface GameState {
id: string; dmID: string;
spectatorID: string;
players: Set<string>; players: Set<string>;
cards: TarokkaGameCard[]; cards: TarokkaGameCard[];
lastUpdated: number; lastUpdated: number;
} }
export interface GameUpdate { export interface GameUpdate {
id: string; dmID: string;
spectatorID: string;
cards: TarokkaGameCard[]; cards: TarokkaGameCard[];
} }