/** * Game Server - Real-time Multiplayer * Handles actual game instances, player connections, and real-time gameplay */ const express = require('express'); const http = require('http'); const socketIo = require('socket.io'); const cors = require('cors'); const helmet = require('helmet'); const compression = require('compression'); const dotenv = require('dotenv'); require('dotenv').config(); const logger = require('./utils/logger'); const connectDB = require('./config/database'); const { initializeGameSystems } = require('./systems/GameSystem'); const SocketHandlers = require('./socket/socketHandlers'); const ServerRegistrationService = require('./services/ServerRegistrationService'); const ModService = require('./services/ModService'); const modRoutes = require('./routes/mods'); const { errorHandler, notFound } = require('./middleware/errorHandler'); const app = express(); const server = http.createServer(app); const io = socketIo(server, { cors: { origin: ["https://galaxystrike.online", "https://api.korvarix.com", "http://localhost:3000"], methods: ["GET", "POST"], credentials: true } }); // Middleware app.use(helmet()); app.use(compression()); app.use(cors({ origin: ["https://galaxystrike.online", "https://api.korvarix.com", "http://localhost:3000"], credentials: true })); app.use(express.json({ limit: '10mb' })); app.use(express.urlencoded({ extended: true })); // Game Server Routes (minimal - mostly for health checks and server management) app.get('/health', (req, res) => { res.status(200).json({ status: 'Game Server OK', service: 'galaxystrikeonline-game', timestamp: new Date().toISOString(), uptime: process.uptime(), activeServers: Object.keys(gameServers).length, connectedPlayers: connectedPlayers.size }); }); // Get server status app.get('/api/game/status', (req, res) => { res.json({ activeServers: Object.keys(gameServers).length, connectedPlayers: connectedPlayers.size, timestamp: new Date().toISOString() }); }); // Mod management routes app.use('/api/mods', modRoutes); // Error handling app.use(notFound); app.use(errorHandler); // Global game server instances const gameServers = {}; let serverRegistration; // Global reference to registration service // Player tracking const connectedPlayers = new Set(); // Track actual player connections let socketHandlers; io.on('connection', (socket) => { logger.info(`Game Server: Player connected - ${socket.id}`); socketHandlers.handleConnection(socket); }); // Handle uncaught errors process.on('uncaughtException', (error) => { logger.error('Uncaught Exception:', error); }); process.on('unhandledRejection', (reason, promise) => { logger.error('Unhandled Rejection at:', promise, 'reason:', reason); }); // Graceful shutdown handlers async function gracefulShutdown(signal) { logger.info(`[GRACEFUL SHUTDOWN] Received ${signal}, shutting down gracefully...`); try { // Stop accepting new connections server.close(async () => { logger.info('[GRACEFUL SHUTDOWN] HTTP server closed'); // Unregister from API if (serverRegistration) { await serverRegistration.stopHeartbeat(); const unregistered = await serverRegistration.unregisterWithAPI(); if (unregistered) { logger.info('[GRACEFUL SHUTDOWN] Server unregistered from API successfully'); } else { logger.warn('[GRACEFUL SHUTDOWN] Failed to unregister from API'); } } // Shutdown mod service await ModService.shutdown(); // Close database connections const mongoose = require('mongoose'); await mongoose.connection.close(); logger.info('[GRACEFUL SHUTDOWN] Database connections closed'); process.exit(0); }); // Force shutdown after 30 seconds setTimeout(() => { logger.error('[GRACEFUL SHUTDOWN] Forced shutdown after timeout'); process.exit(1); }, 30000); } catch (error) { logger.error('[GRACEFUL SHUTDOWN] Error during shutdown:', error); process.exit(1); } } process.on('SIGTERM', () => gracefulShutdown('SIGTERM')); process.on('SIGINT', () => gracefulShutdown('SIGINT')); // Handle Socket.IO adapter errors io.engine.on('connection_error', (err) => { logger.error('Socket.IO connection error:', err); }); io.of('/').adapter.on('error', (err) => { logger.error('Socket.IO adapter error:', err); }); // Initialize database and game systems async function startGameServer() { try { // Connect to database await connectDB(); logger.info('Game Server: Database connected successfully'); // Initialize mod service await ModService.initialize(); logger.info('Game Server: Mod service initialized'); // Initialize game systems await initializeGameSystems(); logger.info('Game Server: Game systems initialized'); // Initialize server registration service const gameServerUrl = `https://api.korvarix.com:${process.env.GAME_PORT || 3002}`; const apiUrl = process.env.API_SERVER_URL || 'https://api.korvarix.com'; const serverName = process.env.SERVER_NAME || 'Game Server'; const serverRegion = process.env.SERVER_REGION || 'us-east'; const maxPlayers = parseInt(process.env.MAX_PLAYERS) || 10; serverRegistration = new ServerRegistrationService(gameServerUrl, apiUrl, serverName, serverRegion, maxPlayers); // Set up player count callback serverRegistration.setPlayerCountCallback(() => connectedPlayers.size); serverRegistration.startHeartbeat(); // Initialize socket handlers socketHandlers = new SocketHandlers(io, gameServers, connectedPlayers); // Make registration service available to socket handlers socketHandlers.serverRegistration = serverRegistration; // Start server const PORT = process.env.GAME_PORT || 3002; // Game Server on port 3002 server.listen(PORT, () => { logger.info(`Game Server running on port ${PORT}`); logger.info('Game Server handles: Real-time Multiplayer, Game Instances, Socket.IO'); logger.info(`Game Server Name: ${serverName}`); logger.info(`Game Server Region: ${serverRegion}`); logger.info(`Game Server URL: ${gameServerUrl}`); logger.info(`API Server URL: ${apiUrl}`); }); } catch (error) { logger.error('Failed to start Game Server:', error); process.exit(1); } } startGameServer(); module.exports = { app, server, io, gameServers };