Initial commit
This commit is contained in:
1150
server/game/GameEngine.js
Normal file
1150
server/game/GameEngine.js
Normal file
File diff suppressed because it is too large
Load Diff
182
server/game/GameManager.js
Normal file
182
server/game/GameManager.js
Normal file
@@ -0,0 +1,182 @@
|
||||
const { GameEngine } = require('../game/GameEngine');
|
||||
const { buildStarterDeck, STARTER_DECKS, ALL_CARDS, CARD_DB } = require('../cards');
|
||||
|
||||
class GameManager {
|
||||
constructor() {
|
||||
this.rooms = new Map();
|
||||
this.playerRooms = new Map();
|
||||
this.games = new Map();
|
||||
}
|
||||
|
||||
createRoom(hostId, hostName, roomName) {
|
||||
const roomId = `room_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
|
||||
const room = {
|
||||
id: roomId,
|
||||
name: roomName || `${hostName}'s Game`,
|
||||
hostId,
|
||||
players: [{ id: hostId, name: hostName, deck: null, ready: false }],
|
||||
status: 'waiting',
|
||||
gameId: null,
|
||||
maxPlayers: 2,
|
||||
};
|
||||
this.rooms.set(roomId, room);
|
||||
this.playerRooms.set(hostId, roomId);
|
||||
return room;
|
||||
}
|
||||
|
||||
joinRoom(roomId, playerId, playerName) {
|
||||
const room = this.rooms.get(roomId);
|
||||
if (!room) return { error: 'Room not found' };
|
||||
if (room.status !== 'waiting') return { error: 'Game already in progress' };
|
||||
if (room.players.length >= room.maxPlayers) return { error: 'Room is full' };
|
||||
if (room.players.find((p) => p.id === playerId)) return { error: 'Already in room' };
|
||||
|
||||
room.players.push({ id: playerId, name: playerName, deck: null, ready: false });
|
||||
this.playerRooms.set(playerId, roomId);
|
||||
return { success: true, room };
|
||||
}
|
||||
|
||||
leaveRoom(playerId) {
|
||||
const roomId = this.playerRooms.get(playerId);
|
||||
if (!roomId) return { error: 'Not in a room' };
|
||||
|
||||
const room = this.rooms.get(roomId);
|
||||
if (!room) {
|
||||
this.playerRooms.delete(playerId);
|
||||
return { error: 'Room not found' };
|
||||
}
|
||||
|
||||
room.players = room.players.filter((p) => p.id !== playerId);
|
||||
this.playerRooms.delete(playerId);
|
||||
|
||||
if (room.players.length === 0) {
|
||||
this.rooms.delete(roomId);
|
||||
if (room.gameId) this.games.delete(room.gameId);
|
||||
return { success: true, roomDeleted: true, roomId };
|
||||
}
|
||||
|
||||
if (room.hostId === playerId) {
|
||||
room.hostId = room.players[0].id;
|
||||
}
|
||||
|
||||
return { success: true, room };
|
||||
}
|
||||
|
||||
selectDeck(playerId, deckColor) {
|
||||
const roomId = this.playerRooms.get(playerId);
|
||||
if (!roomId) return { error: 'Not in a room' };
|
||||
|
||||
const room = this.rooms.get(roomId);
|
||||
if (!room) return { error: 'Room not found' };
|
||||
|
||||
const player = room.players.find((p) => p.id === playerId);
|
||||
if (!player) return { error: 'Player not in room' };
|
||||
|
||||
if (!STARTER_DECKS[deckColor]) return { error: 'Invalid deck color' };
|
||||
|
||||
player.deck = deckColor;
|
||||
player.ready = true;
|
||||
return { success: true, room };
|
||||
}
|
||||
|
||||
selectCustomDeck(playerId, cardIds) {
|
||||
const roomId = this.playerRooms.get(playerId);
|
||||
if (!roomId) return { error: 'Not in a room' };
|
||||
|
||||
const room = this.rooms.get(roomId);
|
||||
if (!room) return { error: 'Room not found' };
|
||||
|
||||
const player = room.players.find((p) => p.id === playerId);
|
||||
if (!player) return { error: 'Player not in room' };
|
||||
|
||||
if (cardIds.length < 40) return { error: 'Deck must have at least 40 cards' };
|
||||
if (cardIds.length > 60) return { error: 'Deck cannot exceed 60 cards' };
|
||||
|
||||
for (const cid of cardIds) {
|
||||
if (!CARD_DB[cid]) return { error: `Invalid card id: ${cid}` };
|
||||
}
|
||||
|
||||
const nonLandCounts = {};
|
||||
for (const cid of cardIds) {
|
||||
const card = CARD_DB[cid];
|
||||
if (card.type !== 'land' || card.subtype !== 'basic') {
|
||||
nonLandCounts[cid] = (nonLandCounts[cid] || 0) + 1;
|
||||
if (nonLandCounts[cid] > 4) {
|
||||
return { error: `Cannot have more than 4 copies of ${card.name}` };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
player.deck = cardIds;
|
||||
player.customDeck = true;
|
||||
player.ready = true;
|
||||
return { success: true, room };
|
||||
}
|
||||
|
||||
startGame(roomId) {
|
||||
const room = this.rooms.get(roomId);
|
||||
if (!room) return { error: 'Room not found' };
|
||||
if (room.players.length < 2) return { error: 'Need at least 2 players' };
|
||||
if (!room.players.every((p) => p.ready)) return { error: 'Not all players are ready' };
|
||||
|
||||
const p1 = room.players[0];
|
||||
const p2 = room.players[1];
|
||||
|
||||
const deck1 = p1.customDeck ? p1.deck : buildStarterDeck(p1.deck);
|
||||
const deck2 = p2.customDeck ? p2.deck : buildStarterDeck(p2.deck);
|
||||
|
||||
const engine = new GameEngine(p1.id, p2.id, deck1, deck2);
|
||||
const initialState = engine.startGame();
|
||||
|
||||
room.status = 'playing';
|
||||
room.gameId = engine.id;
|
||||
this.games.set(engine.id, engine);
|
||||
|
||||
return { success: true, gameId: engine.id, state: initialState };
|
||||
}
|
||||
|
||||
getGame(gameId) {
|
||||
return this.games.get(gameId);
|
||||
}
|
||||
|
||||
handleGameAction(gameId, playerId, action) {
|
||||
const engine = this.games.get(gameId);
|
||||
if (!engine) return { error: 'Game not found' };
|
||||
return engine.handleAction(playerId, action);
|
||||
}
|
||||
|
||||
getGameState(gameId, playerId) {
|
||||
const engine = this.games.get(gameId);
|
||||
if (!engine) return null;
|
||||
return engine.getState(playerId);
|
||||
}
|
||||
|
||||
getRooms() {
|
||||
const roomList = [];
|
||||
for (const room of this.rooms.values()) {
|
||||
roomList.push({
|
||||
id: room.id,
|
||||
name: room.name,
|
||||
playerCount: room.players.length,
|
||||
maxPlayers: room.maxPlayers,
|
||||
status: room.status,
|
||||
host: room.players.find((p) => p.id === room.hostId)?.name || 'Unknown',
|
||||
});
|
||||
}
|
||||
return roomList;
|
||||
}
|
||||
|
||||
getRoomDetails(roomId) {
|
||||
return this.rooms.get(roomId) || null;
|
||||
}
|
||||
|
||||
getCardList() {
|
||||
return ALL_CARDS;
|
||||
}
|
||||
|
||||
getStarterDecks() {
|
||||
return STARTER_DECKS;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { GameManager };
|
||||
Reference in New Issue
Block a user