const express = require('express'); const jwt = require('jsonwebtoken'); const GameServer = require('../models/GameServer'); const logger = require('../utils/logger'); const router = express.Router(); // Middleware to authenticate JWT token const authenticateToken = (req, res, next) => { const token = req.header('Authorization')?.replace('Bearer ', ''); if (!token) { return res.status(401).json({ error: 'Access token required' }); } try { const decoded = jwt.verify(token, process.env.JWT_SECRET || 'fallback_secret'); req.userId = decoded.userId; next(); } catch (error) { res.status(401).json({ error: 'Invalid token' }); } }; // Register new game server (for GameServer instances to register themselves) router.post('/register', async (req, res) => { try { const { serverId, name, type, region, maxPlayers, currentPlayers, gameServerUrl, owner } = req.body; logger.info(`[API SERVER] Game server registration request:`, { serverId, name, type, region, maxPlayers, currentPlayers, gameServerUrl, owner }); // Check if server already exists const existingServer = await GameServer.findOne({ serverId }); if (existingServer) { // Update existing server existingServer.name = name || existingServer.name; existingServer.type = type || existingServer.type; existingServer.region = region || existingServer.region; existingServer.maxPlayers = maxPlayers || existingServer.maxPlayers; existingServer.currentPlayers = currentPlayers !== undefined ? currentPlayers : existingServer.currentPlayers; existingServer.gameServerUrl = gameServerUrl || existingServer.gameServerUrl; existingServer.status = 'waiting'; existingServer.lastActivity = new Date(); await existingServer.save(); logger.info(`[API SERVER] Updated existing server: ${serverId} with ${existingServer.currentPlayers} players`); return res.json({ success: true, message: 'Server updated successfully', server: existingServer }); } // Create new server const newServer = new GameServer({ serverId, name: name || `Game Server ${serverId}`, type: type || 'public', region: region || 'us-east', maxPlayers: maxPlayers || 10, currentPlayers: currentPlayers !== undefined ? currentPlayers : 0, owner: owner || { userId: 'system', username: 'System' }, status: 'waiting', gameServerUrl, createdAt: new Date(), lastActivity: new Date() }); await newServer.save(); logger.info(`[API SERVER] Registered new server: ${serverId}`); res.status(201).json({ success: true, message: 'Server registered successfully', server: newServer }); } catch (error) { logger.error('[API SERVER] Error registering server:', error); res.status(500).json({ success: false, error: 'Failed to register server' }); } }); // Update server status (for GameServer instances to update their status) router.post('/update-status/:serverId', async (req, res) => { try { const { serverId } = req.params; const { currentPlayers, status } = req.body; const server = await GameServer.findOne({ serverId }); if (!server) { return res.status(404).json({ success: false, error: 'Server not found' }); } if (currentPlayers !== undefined) { server.currentPlayers = currentPlayers; } if (status) { server.status = status; } server.lastActivity = new Date(); await server.save(); logger.info(`[API SERVER] Updated server ${serverId} status:`, { currentPlayers: server.currentPlayers, status: server.status }); res.json({ success: true, message: 'Server status updated successfully' }); } catch (error) { logger.error('[API SERVER] Error updating server status:', error); res.status(500).json({ success: false, error: 'Failed to update server status' }); } }); // Unregister game server (for GameServer instances to unregister themselves) router.delete('/unregister/:serverId', async (req, res) => { try { const { serverId } = req.params; logger.info(`[API SERVER] Game server unregistration request:`, { serverId }); // Find and remove server const server = await GameServer.findOneAndDelete({ serverId }); if (!server) { return res.status(404).json({ success: false, error: 'Server not found' }); } logger.info(`[API SERVER] Unregistered server: ${serverId}`); res.json({ success: true, message: 'Server unregistered successfully' }); } catch (error) { logger.error('[API SERVER] Error unregistering server:', error); res.status(500).json({ success: false, error: 'Failed to unregister server' }); } }); // Get server list router.get('/', authenticateToken, async (req, res) => { try { const { type, region } = req.query; // Build filters const filters = {}; if (type) filters.type = type; if (region) filters.region = region; logger.info(`[API SERVER] Fetching servers for user ${req.userId} with filters:`, filters); // Get available servers from database const servers = await GameServer.findAvailableServers(filters); logger.info(`[API SERVER] Found ${servers.length} servers in database`); // Format server list for client const serverList = servers.map(server => ({ id: server.serverId, name: server.name, type: server.type, region: server.region, currentPlayers: server.currentPlayers, maxPlayers: server.maxPlayers, status: server.status, ownerName: server.owner.username, createdAt: server.createdAt, lastActivity: server.lastActivity })); logger.info(`[API SERVER] Returning ${serverList.length} servers to client`); res.json({ success: true, servers: serverList, totalServers: serverList.length }); } catch (error) { logger.error('Error getting server list:', error); res.status(500).json({ error: 'Internal server error' }); } }); // Create new server router.post('/create', authenticateToken, async (req, res) => { try { const { name, type = 'public', maxPlayers = 10, region = 'us-east', settings = {} } = req.body; if (!name) { return res.status(400).json({ error: 'Server name required' }); } // Generate unique server ID const serverId = `server_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; // Get user info from token (you might want to fetch full user data) const ownerUsername = req.body.username || 'Unknown'; // This should come from user data // Create new server in database const newServer = new GameServer({ serverId, name, type, region, maxPlayers, owner: { userId: req.userId, username: ownerUsername }, settings, gameServerUrl: process.env.GAME_SERVER_URL || 'https://api.korvarix.com' }); await newServer.save(); logger.info(`Server created: ${serverId} by user ${req.userId}`); res.status(201).json({ message: 'Server created successfully', server: { id: newServer.serverId, name: newServer.name, type: newServer.type, region: newServer.region, currentPlayers: newServer.currentPlayers, maxPlayers: newServer.maxPlayers, status: newServer.status, ownerName: newServer.owner.username, createdAt: newServer.createdAt } }); } catch (error) { logger.error('Error creating server:', error); res.status(500).json({ error: 'Internal server error' }); } }); // Join server router.post('/:serverId/join', authenticateToken, async (req, res) => { try { const { serverId } = req.params; // Find server in database const server = await GameServer.findOne({ serverId }); if (!server) { return res.status(404).json({ error: 'Server not found' }); } // Check if server can be joined if (!server.canJoin()) { return res.status(400).json({ error: 'Server is full or offline' }); } // Add player to server const playerAdded = server.addPlayer(); if (!playerAdded) { return res.status(400).json({ error: 'Server is full' }); } await server.save(); logger.info(`User ${req.userId} joined server ${serverId}`); res.json({ message: 'Joined server successfully', server: { id: server.serverId, name: server.name, currentPlayers: server.currentPlayers, maxPlayers: server.maxPlayers, gameServerUrl: server.gameServerUrl } }); } catch (error) { logger.error('Error joining server:', error); res.status(500).json({ error: 'Internal server error' }); } }); // Leave server router.post('/:serverId/leave', authenticateToken, async (req, res) => { try { const { serverId } = req.params; // Find server in database const server = await GameServer.findOne({ serverId }); if (!server) { return res.status(404).json({ error: 'Server not found' }); } // Remove player from server const playerRemoved = server.removePlayer(); if (playerRemoved) { await server.save(); logger.info(`User ${req.userId} left server ${serverId}`); } // Update player's current server const Player = require('../models/Player'); await Player.findOneAndUpdate( { userId: req.userId }, { currentServer: null } ); res.json({ message: 'Left server successfully' }); } catch (error) { logger.error('Error leaving server:', error); res.status(500).json({ error: 'Internal server error' }); } }); // Get server details router.get('/:serverId', authenticateToken, async (req, res) => { try { const { serverId } = req.params; const server = await GameServer.findOne({ serverId }); if (!server) { return res.status(404).json({ error: 'Server not found' }); } res.json({ server: { id: server.serverId, name: server.name, type: server.type, region: server.region, currentPlayers: server.currentPlayers, maxPlayers: server.maxPlayers, status: server.status, ownerName: server.owner.username, settings: server.settings, createdAt: server.createdAt, lastActivity: server.lastActivity } }); } catch (error) { logger.error('Error getting server details:', error); res.status(500).json({ error: 'Internal server error' }); } }); // Get user's current server router.get('/user/current', authenticateToken, async (req, res) => { try { const Player = require('../models/Player'); const player = await Player.findOne({ userId: req.userId }); if (!player || !player.currentServer) { return res.json({ currentServer: null }); } const server = await GameServer.findOne({ serverId: player.currentServer }); if (!server) { // Clear invalid server reference await Player.findOneAndUpdate( { userId: req.userId }, { currentServer: null } ); return res.json({ currentServer: null }); } res.json({ currentServer: { id: server.serverId, name: server.name, currentPlayers: server.currentPlayers, maxPlayers: server.maxPlayers } }); } catch (error) { logger.error('Error getting current server:', error); res.status(500).json({ error: 'Internal server error' }); } }); module.exports = router;