This commit is contained in:
2026-01-27 21:43:42 +03:00
parent 1f18abbc33
commit 7d5769ac8b
4 changed files with 295 additions and 59 deletions

View File

@ -27,7 +27,7 @@ function getCard(room, cardId) {
return cardDb[cardId];
}
const rooms = new Map(); // code -> { lobby, gameState, gameStarted, faction, turnTimerInterval, turnTimeLeft, turnTimerWarnFired }
const rooms = new Map(); // code -> { lobby, gameState, gameStarted, faction, turnTimerInterval, turnTimeLeft, turnTimerWarnFired, spectators: [] }
const TURN_SECONDS = 90;
const TURN_WARN_AT = 15;
@ -433,6 +433,7 @@ function getRoomBySocket(socketId) {
for (const room of rooms.values()) {
if (room.lobby?.some((p) => p.id === socketId)) return room;
if (room.gameState?.players?.some((p) => p.id === socketId)) return room;
if (room.spectators?.some((s) => s.id === socketId)) return room;
}
return null;
}
@ -1835,6 +1836,7 @@ io.on('connection', (socket) => {
turnTimerInterval: null,
turnTimeLeft: TURN_SECONDS,
turnTimerWarnFired: false,
spectators: [],
};
rooms.set(code, room);
socket.join(code);
@ -1849,6 +1851,19 @@ io.on('connection', (socket) => {
cleanupEmptyRooms();
});
socket.on('getRoomsList', () => {
const roomsList = Array.from(rooms.entries()).map(([code, room]) => ({
code,
playerCount: room.lobby?.length || 0,
maxPlayers: MAX_PLAYERS,
gameStarted: room.gameStarted || false,
hasAI: room.aiMode || false,
players: room.lobby?.map(p => p.name) || [],
spectators: (room.spectators || []).length
}));
socket.emit('roomsList', roomsList);
});
socket.on('joinRoom', (data) => {
const { code, name } = data || {};
if (!code) {
@ -1860,10 +1875,18 @@ io.on('connection', (socket) => {
socket.emit('error', 'Комната не найдена');
return;
}
if (room.gameStarted) {
socket.emit('error', 'Игра уже началась');
// Игра уже началась - подключаемся как наблюдатель
if (!room.spectators) room.spectators = [];
room.spectators.push({ id: socket.id, name: name || 'Наблюдатель' });
socket.join(code);
socket.emit('joinedAsSpectator', { code, gameState: room.gameState });
broadcastGameState(room); // Отправляем текущее состояние игры
return;
}
// Игра не началась - подключаемся как игрок
if (room.lobby.length >= MAX_PLAYERS) {
socket.emit('error', 'Комната заполнена');
return;
@ -2070,15 +2093,34 @@ io.on('connection', (socket) => {
const hostId = room.gameState.players[0].id;
if (socket.id !== hostId) return;
clearTurnTimer(room);
// Сохраняем список игроков для новой игры
room.lobby = room.gameState.players.map((p) => ({ id: p.id, name: p.name }));
// Сохраняем настройки комнаты
const savedFaction = room.faction;
const savedAIMode = room.aiMode;
room.gameState = null;
room.gameStarted = false;
io.to(room.code).emit('backToLobby');
room.faction = savedFaction;
room.aiMode = savedAIMode;
// Очищаем наблюдателей
if (room.spectators) room.spectators = [];
io.to(room.code).emit('backToLobby', { lobby: room.lobby });
});
socket.on('disconnect', () => {
const room = getRoomBySocket(socket.id);
if (!room) return;
// Проверяем, был ли это наблюдатель
if (room.spectators) {
const specIdx = room.spectators.findIndex(s => s.id === socket.id);
if (specIdx >= 0) {
room.spectators.splice(specIdx, 1);
socket.leave(room.code);
return;
}
}
if (!room.gameStarted) {
room.lobby = room.lobby.filter((p) => p.id !== socket.id);
socket.leave(room.code);