'use strict'; import PlayerId from './players/player-id'; import GamesManager from './game-server/games-manager'; import MariadbConnector from './db/mariadb-connector'; import ServerToolListner from './tools/server-tool-listener'; function Server() { console.log('Starting 12 heroes server'); const io = require('socket.io'); const server = io.listen(2610); let mariadbConn = new MariadbConnector(); let gamesManager = new GamesManager(server, mariadbConn); let authorizedPlayers = new Map(); let connectedPlayers = new Map(); let authorizedPlayersNames = new Set(); server.on('connection', function(socket) { socket.on('disconnect', reason => { console.log('A player disconnected, reason : ' + reason); if ( reason === 'client namespace disconnect' || reason === 'server namespace disconnect' || reason === 'transport close' ) { let username = connectedPlayers.get(socket.id); if (username) { let player = authorizedPlayers.get(username); // If player had created a game, remove it removeAllGamesCreatedByPlayer(username) .then(res => { if (res.affectedRows > 0) { // Tell other clients to reload their games if there were forceClientsReloadGames(); } }) .catch(err => console.log('Error removing game :>> ', err.message)); // Tell game manager a player left, if he was playing if (player.isPlayingGameId >= 0) { gamesManager.playerLeft(player, true); } connectedPlayers.delete(socket.id); player.setConnected(false); player.setSocket(null); console.log(username + ' disconnected'); } } }); socket.on('auth', async (playerName, callback) => { console.log(' Received auth message, player name : ' + playerName); await updatePlayersFromDb(); let response = {}; let kickout = false; if (!authorizedPlayersNames.has(playerName)) { response = { res: 'ko', message: playerName + ' Not found' }; kickout = true; } // If the player is already connected and active else if ( authorizedPlayers.get(playerName).isConnected() && authorizedPlayers.get(playerName).getSocket().connected ) { response = { res: 'ko', message: playerName + ' already connected' }; kickout = true; } else { // Player marked as connected but socket is down, clean it if (authorizedPlayers.get(playerName).isConnected()) { authorizedPlayers .get(playerName) .getSocket() .disconnect(true); } else { // In case server did not detect disconnection and did not clean the pending created games try { await removeAllGamesCreatedByPlayer(playerName); } catch (err) { console.log('Error removing games : ' + err.message); } } response = { res: 'ok', message: playerName + ' connected' }; authorizedPlayers.get(playerName).setConnected(true); authorizedPlayers.get(playerName).setSocket(socket); connectedPlayers.set(socket.id, playerName); } console.log('auth called, result : ', response.message); callback(response); if (kickout === true) { setTimeout(() => { socket.disconnect(true); }, 600); } }); socket.on('games-list', async (playerName, callback) => { let response = {}; try { let games = await getJoinableGames(playerName); response = { res: 'ok', message: games }; } catch (error) { response = { res: 'ko', message: 'Error from server' }; } callback(response); }); socket.on('create-game', async (game, callback) => { let response = {}; try { let id = await addGameDb(game); response = { res: 'ok', message: id }; gamesManager.addPlayerInGame( authorizedPlayers.get(connectedPlayers.get(socket.id)), id, false, true, { deck: game.deck, advRules: game.advRules } ); forceClientsReloadGames(); } catch (error) { console.log('In create-game catch error :>> ', error); response = { res: 'ko', message: 'Error from server' }; } console.log('create-game called, result : ', response.message); callback(response); }); socket.on('join-game', async (gameDetails, callback) => { let result = await gamesManager.addPlayerInGame( authorizedPlayers.get(connectedPlayers.get(socket.id)), gameDetails.id, gameDetails.joinCreatedGame ); let response = {}; if (result === true) { response.res = 'ok'; response.message = 'Game joined'; } else { response.res = 'ko'; response.message = 'Unable to join game'; } callback(response); }); socket.on('leave-game', async (username, callback) => { // Remove player from game he is playing try { let res = removeAllGamesCreatedByPlayer(username); if (res.affectedRows > 0) { forceClientsReloadGames(); } } catch (err) { console.log('Error removing games : ' + err.message); } gamesManager.playerLeft(authorizedPlayers.get(username), false); callback(true); }); }); let updatePlayersFromDb = async function() { try { let usernames = await mariadbConn.getUsernames(); authorizedPlayersNames = new Set(usernames); authorizedPlayersNames.forEach(name => { if (!authorizedPlayers.has(name)) { authorizedPlayers.set(name, new PlayerId(name)); } }); return 'ok'; } catch (error) { console.log('Error getting usernames from DB : ', error); return error.Error; } }; let getCurrentListAuthorizedPlayers = function() { return [...authorizedPlayersNames]; }; let addPlayerDb = async function(username) { console.log('add player in db : ' + username); try { let response = await mariadbConn.addPlayer(username); authorizedPlayersNames.add(username); authorizedPlayers.set(username, new PlayerId(username)); return 'OK ' + JSON.stringify(response); } catch (err) { return 'KO ' + err.message; } }; let removePlayerDb = async function(username) { console.log('remove player in db : ' + username); try { let response = await mariadbConn.removePlayer(username); authorizedPlayersNames.delete(username); authorizedPlayers.delete(username); return 'OK ' + JSON.stringify(response); } catch (err) { return 'KO ' + err.message; } }; let addGameDb = async function(game) { try { let response = await mariadbConn.addNewGame(game); return response; } catch (err) { console.log('KO ' + err.message); throw err; } }; let removeGameDb = async function(method, ...args) { try { let response; switch (method) { case 'byId': response = await mariadbConn.removeGameById(args[0]); break; case 'byPlayer1': response = await mariadbConn.removeGamesByPlayer1(args[0]); break; case 'byPlayerAny': response = await mariadbConn.removeGamesByPlayerAny(args[0]); break; case 'byStatus': response = await mariadbConn.removeGamesByStatus(args[0]); break; case 'byDays': response = await mariadbConn.removeGamesByDays(args[0]); break; case 'finishedByDays': response = await mariadbConn.removeFinishedGamesByDays(args[0]); break; default: return 'KO : Unknown method to remove game from DB : ' + method; } return 'OK ' + JSON.stringify(response); } catch (err) { return 'KO ' + err.message; } }; let getJoinableGames = async function(username) { try { let games = await mariadbConn.getJoinableGamesForPlayer(username); return games; } catch (err) { console.log('KO : not able to get games : ' + err); throw err; } }; let removeAllGamesCreatedByPlayer = async function(playerName) { let result = await mariadbConn.removeCreatedGamesByPlayer1(playerName); return result; }; let forceClientsReloadGames = function() { server.emit('reload-games-list'); }; return { updatePlayersFromDb, getCurrentListAuthorizedPlayers, addPlayerDb, removePlayerDb, addGameDb, removeGameDb, getJoinableGames }; } let server = new Server(); let serverToolListner = new ServerToolListner(server); serverToolListner.listen(1664);