Исправление Гипнотического взгляда.
This commit is contained in:
parent
0e7ef20332
commit
35fe54e345
151
bc.js
151
bc.js
@ -1,7 +1,7 @@
|
||||
// bc.js - Главный файл сервера Battle Club
|
||||
|
||||
const express = require('express');
|
||||
const http = require('http'); // Используем HTTP, так как SSL будет на Node.js прокси (server.js)
|
||||
const http = require('http');
|
||||
const { Server } = require('socket.io');
|
||||
const path = require('path');
|
||||
|
||||
@ -16,13 +16,10 @@ const app = express();
|
||||
const server = http.createServer(app);
|
||||
|
||||
// Настройка Socket.IO
|
||||
// cors options могут потребоваться, если клиент и сервер работают на разных портах/доменах
|
||||
const io = new Server(server, {
|
||||
cors: {
|
||||
origin: "https://pavel-chagovsky.com:3200", // Указываем точный origin, включая порт, откуда придет запрос К ПРОКСИ
|
||||
// Если доступ будет с нескольких доменов или портов, можно использовать массив:
|
||||
// origin: ["https://pavel-chagovsky.com:3200", "https://oleg-okhotnikov.ru:3200"],
|
||||
// Или для разработки можно временно использовать "*", но это менее безопасно:
|
||||
// origin: "*",
|
||||
origin: "*", // Разрешить подключение с любого домена (для разработки). В продакшене лучше указать конкретный домен клиента.
|
||||
methods: ["GET", "POST"]
|
||||
}
|
||||
});
|
||||
@ -34,132 +31,198 @@ app.use(express.static(path.join(__dirname, 'public')));
|
||||
const gameManager = new GameManager(io);
|
||||
|
||||
// Хранилище информации о залогиненных пользователях по socket.id
|
||||
// В более сложном приложении здесь может быть Redis или другое внешнее хранилище сессий
|
||||
const loggedInUsers = {}; // { socket.id: { userId: ..., username: ... } }
|
||||
|
||||
// Обработка подключений Socket.IO
|
||||
io.on('connection', (socket) => {
|
||||
console.log(`[BC App HTTP] Socket.IO User connected: ${socket.id}`);
|
||||
console.log(`[Socket.IO] Пользователь подключился: ${socket.id}`);
|
||||
|
||||
socket.userData = null;
|
||||
// Привязываем user data к сокету (пока пустые)
|
||||
socket.userData = null; // { userId: ..., username: ... }
|
||||
|
||||
// При подключении клиента, если он уже залогинен (например, по cookie/token, что здесь не реализовано,
|
||||
// но может быть добавлено), нужно восстановить его user data и проверить, не в игре ли он.
|
||||
// В текущей простой реализации, мы полагаемся на то, что клиент после коннекта сам отправит логин,
|
||||
// если он был залогинен. Но если бы была проверка сессии, логика была бы тут.
|
||||
// Добавляем вызов handleRequestGameState при коннекте, если есть user data (для примера,
|
||||
// но для полной реализации нужны cookies/токены)
|
||||
// if (socket.userData?.userId) { // Эта проверка сработает только после успешного логина в текущей сессии
|
||||
// gameManager.handleRequestGameState(socket, socket.userData.userId); // Передаем объект socket
|
||||
// }
|
||||
|
||||
|
||||
// --- Обработчики событий Аутентификации ---
|
||||
socket.on('register', async (data) => {
|
||||
console.log(`[BC App HTTP Socket.IO] Register attempt for username: "${data?.username}" from ${socket.id}`);
|
||||
console.log(`[Socket.IO] Register attempt for username: "${data?.username}" from ${socket.id}`);
|
||||
const result = await auth.registerUser(data?.username, data?.password);
|
||||
if (result.success) {
|
||||
console.log(`[BC App HTTP Socket.IO] Registration successful for ${result.username} (${result.userId})`);
|
||||
console.log(`[Socket.IO] Registration successful for ${result.username} (${result.userId})`);
|
||||
} else {
|
||||
console.warn(`[BC App HTTP Socket.IO] Registration failed for "${data?.username}": ${result.message}`);
|
||||
console.warn(`[Socket.IO] Registration failed for "${data?.username}": ${result.message}`);
|
||||
}
|
||||
socket.emit('registerResponse', result);
|
||||
});
|
||||
|
||||
socket.on('login', async (data) => {
|
||||
console.log(`[BC App HTTP Socket.IO] Login attempt for username: "${data?.username}" from ${socket.id}`);
|
||||
console.log(`[Socket.IO] Login attempt for username: "${data?.username}" from ${socket.id}`);
|
||||
const result = await auth.loginUser(data?.username, data?.password);
|
||||
if (result.success) {
|
||||
console.log(`[BC App HTTP Socket.IO] Login successful for ${result.username} (${result.userId}). Assigning to socket ${socket.id}.`);
|
||||
console.log(`[Socket.IO] Login successful for ${result.username} (${result.userId}). Assigning to socket ${socket.id}.`);
|
||||
// Сохраняем информацию о пользователе в сессии сокета
|
||||
socket.userData = { userId: result.userId, username: result.username };
|
||||
loggedInUsers[socket.id] = socket.userData;
|
||||
|
||||
// Проверяем, есть ли у пользователя активная игра при логине (если он был отключен)
|
||||
// ИСПРАВЛЕНИЕ: Передаем объект socket
|
||||
gameManager.handleRequestGameState(socket, socket.userData.userId);
|
||||
|
||||
} else {
|
||||
console.warn(`[BC App HTTP Socket.IO] Login failed for "${data?.username}": ${result.message}`);
|
||||
socket.userData = null;
|
||||
console.warn(`[Socket.IO] Login failed for "${data?.username}": ${result.message}`);
|
||||
socket.userData = null; // Убеждаемся, что данные пользователя на сокете сброшены
|
||||
if (loggedInUsers[socket.id]) delete loggedInUsers[socket.id];
|
||||
}
|
||||
socket.emit('loginResponse', result);
|
||||
});
|
||||
|
||||
socket.on('logout', () => {
|
||||
console.log(`[BC App HTTP Socket.IO] Logout for user ${socket.userData?.username || socket.id}`);
|
||||
console.log(`[Socket.IO] Logout for user ${socket.userData?.username || socket.id}`);
|
||||
// Уведомляем gameManager о дисконнекте (для корректного выхода из игры, если в ней был)
|
||||
// Game Manager сам очистит ссылку socketToGame[socket.id] при handleDisconnect
|
||||
// ИСПРАВЛЕНИЕ: Передаем userId или socket.id в handleDisconnect
|
||||
gameManager.handleDisconnect(socket.id, socket.userData?.userId || socket.id);
|
||||
|
||||
// Очищаем информацию о пользователе на сокете и в хранилище
|
||||
socket.userData = null;
|
||||
if (loggedInUsers[socket.id]) delete loggedInUsers[socket.id];
|
||||
|
||||
// Клиент должен сам переключиться на экран аутентификации
|
||||
});
|
||||
|
||||
// --- Обработчики событий Управления Играми ---
|
||||
|
||||
socket.on('createGame', (data) => {
|
||||
const identifier = socket.userData?.userId || socket.id;
|
||||
// Пользователь, даже не залогиненный, может создать AI игру (идентифицируется по socket.id)
|
||||
// Для PvP игры нужна аутентификация (идентификация по userId)
|
||||
const identifier = socket.userData?.userId || socket.id; // Используем userId для залогиненных, socket.id для гостей
|
||||
const mode = data?.mode || 'ai';
|
||||
|
||||
if (mode === 'pvp' && !socket.userData) {
|
||||
socket.emit('gameError', { message: 'Необходимо войти в систему для создания PvP игры.' });
|
||||
return;
|
||||
}
|
||||
console.log(`[BC App HTTP Socket.IO] Create Game request from ${socket.userData?.username || socket.id} (Identifier: ${identifier}). Mode: ${mode}, Character: ${data?.characterKey}`);
|
||||
const characterKey = data?.characterKey || 'elena';
|
||||
gameManager.createGame(socket, mode, characterKey, identifier);
|
||||
|
||||
console.log(`[Socket.IO] Create Game request from ${socket.userData?.username || socket.id} (Identifier: ${identifier}). Mode: ${mode}, Character: ${data?.characterKey}`);
|
||||
|
||||
const characterKey = data?.characterKey || 'elena'; // По умолчанию Елена
|
||||
gameManager.createGame(socket, mode, characterKey, identifier); // Передаем идентификатор
|
||||
|
||||
});
|
||||
|
||||
socket.on('joinGame', (data) => {
|
||||
if (!socket.userData) {
|
||||
if (!socket.userData) { // Проверяем, залогинен ли пользователь
|
||||
socket.emit('gameError', { message: 'Необходимо войти в систему для присоединения к игре.' });
|
||||
return;
|
||||
}
|
||||
console.log(`[BC App HTTP Socket.IO] Join Game request from ${socket.userData.username} (${socket.id}). Game ID: ${data?.gameId}`);
|
||||
console.log(`[Socket.IO] Join Game request from ${socket.userData.username} (${socket.id}). Game ID: ${data?.gameId}`);
|
||||
const gameId = data?.gameId;
|
||||
const identifier = socket.userData.userId;
|
||||
const identifier = socket.userData.userId; // Присоединиться может только залогиненный
|
||||
|
||||
if (gameId) {
|
||||
gameManager.joinGame(socket, gameId, identifier);
|
||||
gameManager.joinGame(socket, gameId, identifier); // Передаем идентификатор
|
||||
} else {
|
||||
socket.emit('gameError', { message: 'Не указан ID игры для присоединения.' });
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('findRandomGame', (data) => {
|
||||
if (!socket.userData) {
|
||||
if (!socket.userData) { // Проверяем, залогинен ли пользователь
|
||||
socket.emit('gameError', { message: 'Необходимо войти в систему для поиска игры.' });
|
||||
return;
|
||||
}
|
||||
console.log(`[BC App HTTP Socket.IO] Find Random Game request from ${socket.userData.username} (${socket.id}). Preferred Character: ${data?.characterKey}`);
|
||||
const characterKey = data?.characterKey || 'elena';
|
||||
const identifier = socket.userData.userId;
|
||||
gameManager.findAndJoinRandomPvPGame(socket, characterKey, identifier);
|
||||
console.log(`[Socket.IO] Find Random Game request from ${socket.userData.username} (${socket.id}). Preferred Character: ${data?.characterKey}`);
|
||||
const characterKey = data?.characterKey || 'elena'; // Предпочитаемый персонаж для создания, если не найдено
|
||||
const identifier = socket.userData.userId; // Ищет и создает только залогиненный
|
||||
|
||||
gameManager.findAndJoinRandomPvPGame(socket, characterKey, identifier); // Передаем идентификатор
|
||||
});
|
||||
|
||||
socket.on('requestPvPGameList', () => {
|
||||
console.log(`[BC App HTTP Socket.IO] Request PvP Game List from ${socket.userData?.username || socket.id}`);
|
||||
// Список игр доступен всем, даже не залогиненным, но присоединиться можно только залогиненным
|
||||
// if (!socket.userData) {
|
||||
// socket.emit('gameError', { message: 'Необходимо войти в систему для просмотра игр.' });
|
||||
// return;
|
||||
// }
|
||||
console.log(`[Socket.IO] Request PvP Game List from ${socket.userData?.username || socket.id}`);
|
||||
const availableGames = gameManager.getAvailablePvPGamesListForClient();
|
||||
socket.emit('availablePvPGamesList', availableGames);
|
||||
});
|
||||
|
||||
// Обработчик для клиента, запрашивающего состояние игры (например, при переподключении)
|
||||
socket.on('requestGameState', () => {
|
||||
// Запрашивать состояние игры может только залогиненный пользователь, т.к. только у них есть userId для идентификации
|
||||
if (!socket.userData) {
|
||||
console.log(`[BC App HTTP Socket.IO] Request Game State from unauthenticated socket ${socket.id}.`);
|
||||
console.log(`[Socket.IO] Request Game State from unauthenticated socket ${socket.id}.`);
|
||||
socket.emit('gameNotFound', { message: 'Необходимо войти для восстановления игры.' });
|
||||
return;
|
||||
}
|
||||
console.log(`[BC App HTTP Socket.IO] Request Game State from ${socket.userData.username} (${socket.id}).`);
|
||||
console.log(`[Socket.IO] Request Game State from ${socket.userData.username} (${socket.id}).`);
|
||||
// ИСПРАВЛЕНИЕ: Передаем объект socket и identifier (userId)
|
||||
gameManager.handleRequestGameState(socket, socket.userData.userId);
|
||||
});
|
||||
|
||||
|
||||
// --- Обработчик события Игрового Действия ---
|
||||
socket.on('playerAction', (actionData) => {
|
||||
// Действие в игре может совершить как залогиненный (PvP), так и не залогиненный (AI) игрок.
|
||||
// Используем userId для залогиненных, socket.id для гостей.
|
||||
const identifier = socket.userData?.userId || socket.id;
|
||||
gameManager.handlePlayerAction(identifier, actionData);
|
||||
|
||||
// Game Manager сам проверит, находится ли идентификатор в игре и его ли сейчас ход
|
||||
// ИСПРАВЛЕНИЕ: Передаем идентификатор вместо socket.id
|
||||
gameManager.handlePlayerAction(identifier, actionData); // Передаем идентификатор
|
||||
});
|
||||
|
||||
|
||||
// --- Обработчик отключения сокета ---
|
||||
socket.on('disconnect', (reason) => {
|
||||
const identifier = socket.userData?.userId || socket.id;
|
||||
console.log(`[BC App HTTP Socket.IO] User disconnected: ${socket.id} (Причина: ${reason}). Identifier: ${identifier}`);
|
||||
gameManager.handleDisconnect(socket.id, identifier);
|
||||
const identifier = socket.userData?.userId || socket.id; // Используем userId для залогиненных, socket.id для гостей
|
||||
console.log(`[Socket.IO] Пользователь отключился: ${socket.id} (Причина: ${reason}). Identifier: ${identifier}`);
|
||||
|
||||
// Уведомляем gameManager о дисконнекте, чтобы он обновил состояние игры.
|
||||
// Передаем идентификатор пользователя.
|
||||
gameManager.handleDisconnect(socket.id, identifier); // Передаем как socketId, так и identifier
|
||||
|
||||
// Удаляем пользователя из списка залогиненных, если был там
|
||||
if (loggedInUsers[socket.id]) {
|
||||
delete loggedInUsers[socket.id];
|
||||
}
|
||||
// Если сокет не был залогинен, его identifier был socket.id.
|
||||
// Связь userIdentifierToGameId будет очищена в gameManager.handleDisconnect, если игра пуста.
|
||||
});
|
||||
|
||||
// Опционально: отправка списка активных игр на сервере для отладки (по запросу с консоли или админки)
|
||||
// global.getActiveGames = () => gameManager.getActiveGamesList();
|
||||
// console.log("Type getActiveGames() in server console to list games.");
|
||||
});
|
||||
|
||||
// Запуск HTTP сервера
|
||||
const PORT = process.env.BC_INTERNAL_PORT || 3200; // Внутренний порт для bc.js
|
||||
const HOSTNAME = '127.0.0.1'; // Слушать ТОЛЬКО на localhost
|
||||
|
||||
server.listen(PORT, HOSTNAME, () => { // Явно указываем HOSTNAME
|
||||
console.log(`Battle Club HTTP Application Server running at http://${HOSTNAME}:${PORT}`);
|
||||
console.log(`This server should only be accessed locally by the reverse proxy.`);
|
||||
const PORT = process.env.PORT || 3200; // Использовать порт из переменных окружения или 3000 по умолчанию
|
||||
server.listen(PORT, () => {
|
||||
console.log(`Server running on port ${PORT}`);
|
||||
console.log(`Serving static files from: ${path.join(__dirname, 'public')}`);
|
||||
// console.log("Database connection pool created/checked (from db.js require)."); // db.js уже логирует
|
||||
});
|
||||
|
||||
// Обработка необработанных промис-ошибок
|
||||
process.on('unhandledRejection', (reason, promise) => {
|
||||
console.error('[BC App HTTP UNHANDLED REJECTION] Unhandled Rejection at:', promise, 'reason:', reason);
|
||||
console.error('[UNHANDLED REJECTION] Unhandled Rejection at:', promise, 'reason:', reason);
|
||||
// Логировать ошибку, возможно, завершить процесс в продакшене
|
||||
});
|
||||
|
||||
process.on('uncaughtException', (err) => {
|
||||
console.error('[BC App HTTP UNCAUGHT EXCEPTION] Caught exception:', err);
|
||||
console.error('[UNCAUGHT EXCEPTION] Caught exception:', err);
|
||||
// Логировать ошибку, выполнить очистку ресурсов, и завершить процесс
|
||||
// В продакшене здесь может быть более сложная логика, например, graceful shutdown
|
||||
// process.exit(1); // Аварийное завершение процесса - можно раскомментировать в продакшене
|
||||
});
|
669
public/js/ui.js
669
public/js/ui.js
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user