bc/bc.js
2025-05-16 17:21:14 +00:00

165 lines
8.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// bc.js - Главный файл сервера Battle Club
const express = require('express');
const http = require('http'); // Используем HTTP, так как SSL будет на Node.js прокси (server.js)
const { Server } = require('socket.io');
const path = require('path');
//
// Импорт серверных модулей
const auth = require('./server_modules/auth');
const GameManager = require('./server_modules/gameManager');
const db = require('./server_modules/db'); // Импорт для инициализации соединения с БД (хотя пул создается при require)
const GAME_CONFIG = require('./server_modules/config'); // Конфиг игры
// gameData импортируется внутри GameInstance и GameLogic
const app = express();
const server = http.createServer(app);
// Настройка Socket.IO
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: "*",
methods: ["GET", "POST"]
}
});
// Раздача статических файлов из папки 'public'
app.use(express.static(path.join(__dirname, 'public')));
// Создаем экземпляр GameManager
const gameManager = new GameManager(io);
// Хранилище информации о залогиненных пользователях по socket.id
const loggedInUsers = {}; // { socket.id: { userId: ..., username: ... } }
// Обработка подключений Socket.IO
io.on('connection', (socket) => {
console.log(`[BC App HTTP] Socket.IO User connected: ${socket.id}`);
socket.userData = null;
socket.on('register', async (data) => {
console.log(`[BC App HTTP 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})`);
} else {
console.warn(`[BC App HTTP 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}`);
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}.`);
socket.userData = { userId: result.userId, username: result.username };
loggedInUsers[socket.id] = socket.userData;
gameManager.handleRequestGameState(socket, socket.userData.userId);
} else {
console.warn(`[BC App HTTP 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}`);
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;
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);
});
socket.on('joinGame', (data) => {
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}`);
const gameId = data?.gameId;
const identifier = socket.userData.userId;
if (gameId) {
gameManager.joinGame(socket, gameId, identifier);
} else {
socket.emit('gameError', { message: 'Не указан ID игры для присоединения.' });
}
});
socket.on('findRandomGame', (data) => {
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);
});
socket.on('requestPvPGameList', () => {
console.log(`[BC App HTTP Socket.IO] Request PvP Game List from ${socket.userData?.username || socket.id}`);
const availableGames = gameManager.getAvailablePvPGamesListForClient();
socket.emit('availablePvPGamesList', availableGames);
});
socket.on('requestGameState', () => {
if (!socket.userData) {
console.log(`[BC App HTTP 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}).`);
gameManager.handleRequestGameState(socket, socket.userData.userId);
});
socket.on('playerAction', (actionData) => {
const identifier = socket.userData?.userId || 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);
if (loggedInUsers[socket.id]) {
delete loggedInUsers[socket.id];
}
});
});
// Запуск 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.`);
console.log(`Serving static files from: ${path.join(__dirname, 'public')}`);
});
// Обработка необработанных промис-ошибок
process.on('unhandledRejection', (reason, promise) => {
console.error('[BC App HTTP UNHANDLED REJECTION] Unhandled Rejection at:', promise, 'reason:', reason);
});
process.on('uncaughtException', (err) => {
console.error('[BC App HTTP UNCAUGHT EXCEPTION] Caught exception:', err);
});