166 lines
9.6 KiB
JavaScript
166 lines
9.6 KiB
JavaScript
// bc.js (или server.js - ваш основной файл сервера)
|
||
const express = require('express');
|
||
const http = require('http');
|
||
const socketIo = require('socket.io');
|
||
const path = require('path');
|
||
//hello
|
||
// Серверные модули
|
||
const GameManager = require('./server_modules/gameManager');
|
||
const authController = require('./server_modules/auth'); // Ваш модуль аутентификации
|
||
// const GAME_CONFIG = require('./server_modules/config'); // Не используется напрямую здесь, но может быть полезен для отладки
|
||
|
||
const hostname = 'localhost'; // или '0.0.0.0' для доступа извне
|
||
const app = express();
|
||
const server = http.createServer(app);
|
||
const io = socketIo(server, {
|
||
cors: {
|
||
origin: "*", // Разрешить все источники для простоты разработки. В продакшене укажите конкретный домен клиента.
|
||
methods: ["GET", "POST"]
|
||
}
|
||
});
|
||
|
||
const PORT = process.env.PORT || 3200;
|
||
|
||
// Статическое обслуживание файлов из папки 'public'
|
||
app.use(express.static(path.join(__dirname, 'public')));
|
||
|
||
// Создание экземпляра GameManager
|
||
const gameManager = new GameManager(io);
|
||
|
||
io.on('connection', (socket) => {
|
||
console.log(`[Server BC.JS] New client connected: ${socket.id}`);
|
||
|
||
// При подключении нового клиента, отправляем ему текущий список доступных PvP игр
|
||
const availableGames = gameManager.getAvailablePvPGamesListForClient();
|
||
socket.emit('availablePvPGamesList', availableGames);
|
||
|
||
// Обработчик запроса на обновление списка PvP игр
|
||
socket.on('requestPvPGameList', () => {
|
||
const currentAvailableGames = gameManager.getAvailablePvPGamesListForClient();
|
||
socket.emit('availablePvPGamesList', currentAvailableGames);
|
||
});
|
||
|
||
// --- Аутентификация ---
|
||
socket.on('register', async (data) => {
|
||
console.log(`[Server BC.JS] Received 'register' event from ${socket.id} with username: ${data?.username}`);
|
||
if (!data || typeof data.username !== 'string' || typeof data.password !== 'string') {
|
||
socket.emit('registerResponse', { success: false, message: 'Некорректные данные запроса для регистрации.' });
|
||
return;
|
||
}
|
||
const result = await authController.registerUser(data.username, data.password);
|
||
socket.emit('registerResponse', result);
|
||
});
|
||
|
||
socket.on('login', async (data) => {
|
||
console.log(`[Server BC.JS] Received 'login' event from ${socket.id} with username: ${data?.username}`);
|
||
if (!data || typeof data.username !== 'string' || typeof data.password !== 'string') {
|
||
socket.emit('loginResponse', { success: false, message: 'Некорректные данные запроса для входа.' });
|
||
return;
|
||
}
|
||
const result = await authController.loginUser(data.username, data.password);
|
||
if (result.success) {
|
||
// Сохраняем данные пользователя в объекте сокета для последующего использования
|
||
socket.userData = { userId: result.userId, username: result.username };
|
||
console.log(`[Server BC.JS] User ${result.username} (ID: ${result.userId}) associated with socket ${socket.id}. Welcome!`);
|
||
}
|
||
socket.emit('loginResponse', result);
|
||
});
|
||
|
||
socket.on('logout', () => {
|
||
const username = socket.userData?.username || socket.id;
|
||
console.log(`[Server BC.JS] Received 'logout' event from ${username}.`);
|
||
if (socket.userData) {
|
||
// При выходе пользователя, обрабатываем его возможное участие в играх
|
||
gameManager.handleDisconnect(socket.id, socket.userData.userId); // Используем userId для более точной обработки
|
||
delete socket.userData; // Удаляем данные пользователя из сокета
|
||
console.log(`[Server BC.JS] User data cleared for ${username}.`);
|
||
}
|
||
// Можно отправить подтверждение выхода, если нужно
|
||
// socket.emit('logoutResponse', { success: true, message: 'Вы успешно вышли.' });
|
||
});
|
||
|
||
// --- Управление Играми ---
|
||
socket.on('createGame', (data) => {
|
||
if (!socket.userData) {
|
||
socket.emit('gameError', { message: "Ошибка: Вы не авторизованы для создания игры." });
|
||
return;
|
||
}
|
||
const mode = data?.mode || 'ai'; // 'ai' или 'pvp'
|
||
const characterKey = (data?.characterKey === 'almagest') ? 'almagest' : 'elena'; // По умолчанию Елена
|
||
console.log(`[Server BC.JS] User ${socket.userData.username} (socket: ${socket.id}) requests createGame. Mode: ${mode}, Character: ${characterKey}`);
|
||
gameManager.createGame(socket, mode, characterKey, socket.userData.userId);
|
||
});
|
||
|
||
socket.on('joinGame', (data) => {
|
||
if (!socket.userData) {
|
||
socket.emit('gameError', { message: "Ошибка: Вы не авторизованы для присоединения к игре." });
|
||
return;
|
||
}
|
||
console.log(`[Server BC.JS] User ${socket.userData.username} (socket: ${socket.id}) requests joinGame for ID: ${data?.gameId}`);
|
||
if (data && typeof data.gameId === 'string') {
|
||
gameManager.joinGame(socket, data.gameId, socket.userData.userId);
|
||
} else {
|
||
socket.emit('gameError', { message: 'Ошибка присоединения: неверный формат ID игры.' });
|
||
}
|
||
});
|
||
|
||
socket.on('findRandomGame', (data) => {
|
||
if (!socket.userData) {
|
||
socket.emit('gameError', { message: "Ошибка: Вы не авторизованы для поиска игры." });
|
||
return;
|
||
}
|
||
const characterKey = (data?.characterKey === 'almagest') ? 'almagest' : 'elena';
|
||
console.log(`[Server BC.JS] User ${socket.userData.username} (socket: ${socket.id}) requests findRandomGame. Preferred Character: ${characterKey}`);
|
||
gameManager.findAndJoinRandomPvPGame(socket, characterKey, socket.userData.userId);
|
||
});
|
||
|
||
// --- Игровые Действия ---
|
||
socket.on('playerAction', (data) => {
|
||
if (!socket.userData) {
|
||
// Если пользователь не авторизован, но пытается совершить действие (маловероятно при правильной логике клиента)
|
||
socket.emit('gameError', { message: "Ошибка: Вы не авторизованы для совершения этого действия." });
|
||
return;
|
||
}
|
||
// GameManager сам проверит, принадлежит ли этот сокет к активной игре
|
||
gameManager.handlePlayerAction(socket.id, data);
|
||
});
|
||
|
||
// Обработчик 'requestRestart' удален, так как эта функциональность заменена на "возврат в меню"
|
||
|
||
// --- Отключение Клиента ---
|
||
socket.on('disconnect', (reason) => {
|
||
const username = socket.userData?.username || socket.id;
|
||
console.log(`[Server BC.JS] Client ${username} disconnected. Reason: ${reason}. Socket ID: ${socket.id}`);
|
||
// Передаем userId, если он есть, для более точной обработки в GameManager
|
||
// (например, для удаления его ожидающих игр или корректного завершения активной игры)
|
||
const userId = socket.userData?.userId;
|
||
gameManager.handleDisconnect(socket.id, userId);
|
||
// socket.userData автоматически очистится для этого объекта socket при его удалении из io.sockets
|
||
});
|
||
|
||
// Для отладки: вывод списка активных игр каждые N секунд
|
||
// setInterval(() => {
|
||
// console.log("--- Active Games ---");
|
||
// const activeGames = gameManager.getActiveGamesList();
|
||
// if (activeGames.length > 0) {
|
||
// activeGames.forEach(game => {
|
||
// console.log(`ID: ${game.id}, Mode: ${game.mode}, Players: ${game.playerCount}, GameOver: ${game.isGameOver}, P1: ${game.playerSlot}, P2: ${game.opponentSlot}, Owner: ${game.ownerUserId}, Pending: ${game.pending}`);
|
||
// });
|
||
// } else {
|
||
// console.log("No active games.");
|
||
// }
|
||
// console.log("--- Pending PvP Games IDs ---");
|
||
// console.log(gameManager.pendingPvPGames.map(id => id.substring(0,8)));
|
||
// console.log("--- User to Pending Game Map ---");
|
||
// console.log(gameManager.userToPendingGame);
|
||
// console.log("---------------------");
|
||
// }, 30000); // Каждые 30 секунд
|
||
});
|
||
|
||
server.listen(PORT, hostname, () => {
|
||
console.log(`==== Medieval Clash Server ====`);
|
||
console.log(` Listening on http://${hostname}:${PORT}`);
|
||
console.log(` Public files served from: ${path.join(__dirname, 'public')}`);
|
||
console.log(` Waiting for connections...`);
|
||
console.log(`===============================`);
|
||
}); |