server.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. 'use strict';
  2. import PlayerId from './players/player-id';
  3. import GamesManager from './game-server/games-manager';
  4. import MariadbConnector from './db/mariadb-connector';
  5. import ServerToolListner from './tools/server-tool-listener';
  6. function Server() {
  7. console.log('Starting 12 heroes server');
  8. const io = require('socket.io');
  9. const server = io.listen(2610);
  10. let mariadbConn = new MariadbConnector();
  11. let gamesManager = new GamesManager(server, mariadbConn);
  12. let authorizedPlayers = new Map();
  13. let connectedPlayers = new Map();
  14. let authorizedPlayersNames = new Set();
  15. server.on('connection', function(socket) {
  16. console.log('A player connected with id : ' + socket.id);
  17. socket.on('disconnect', reason => {
  18. console.log('A player disconnected, reason : ' + reason);
  19. if (
  20. reason === 'client namespace disconnect' ||
  21. reason === 'server namespace disconnect' ||
  22. reason === 'transport close'
  23. ) {
  24. let username = connectedPlayers.get(socket.id);
  25. if (username) {
  26. let player = authorizedPlayers.get(username);
  27. // First, tell game manager a player left, is he was playing
  28. if (player.isPlayingGameId >= 0) {
  29. gamesManager.playerLeft(player, true);
  30. }
  31. // If player had created a game, remove it
  32. removeAllGamesCreatedByPlayer(username)
  33. .then(res => {
  34. if (res.affectedRows > 0) {
  35. // Tell other clients to reload their games if there were
  36. forceClientsReloadGames();
  37. }
  38. })
  39. .catch(err => console.log('Error removing game :>> ', err.message));
  40. connectedPlayers.delete(socket.id);
  41. player.setConnected(false);
  42. player.setSocket(null);
  43. console.log(username + ' disconnected');
  44. }
  45. }
  46. });
  47. socket.on('connect', () => {
  48. console.log('Connected to server');
  49. });
  50. socket.on('auth', async (playerName, callback) => {
  51. console.log(' Received auth message, player name : ' + playerName);
  52. await updatePlayersFromDb();
  53. let response = {};
  54. let kickout = false;
  55. if (!authorizedPlayersNames.has(playerName)) {
  56. response = {
  57. res: 'ko',
  58. message: playerName + ' Not found'
  59. };
  60. kickout = true;
  61. }
  62. // If the player is already connected and active
  63. else if (
  64. authorizedPlayers.get(playerName).isConnected() &&
  65. authorizedPlayers.get(playerName).getSocket().connected
  66. ) {
  67. response = {
  68. res: 'ko',
  69. message: playerName + ' already connected'
  70. };
  71. kickout = true;
  72. } else {
  73. // Player marked as connected but socket is down, clean it
  74. if (authorizedPlayers.get(playerName).isConnected()) {
  75. authorizedPlayers
  76. .get(playerName)
  77. .getSocket()
  78. .disconnect(true);
  79. } else {
  80. // In case server did not detect disconnection and did not clean the pending created games
  81. try {
  82. await removeAllGamesCreatedByPlayer(playerName);
  83. } catch (err) {
  84. console.log('Error removing games : ' + err.message);
  85. }
  86. }
  87. response = {
  88. res: 'ok',
  89. message: playerName + ' connected'
  90. };
  91. authorizedPlayers.get(playerName).setConnected(true);
  92. authorizedPlayers.get(playerName).setSocket(socket);
  93. connectedPlayers.set(socket.id, playerName);
  94. }
  95. callback(response);
  96. if (kickout === true) {
  97. setTimeout(() => {
  98. socket.disconnect(true);
  99. }, 600);
  100. }
  101. });
  102. socket.on('games-list', async (playerName, callback) => {
  103. console.log(' Received games-list message, player name : ' + playerName);
  104. let response = {};
  105. try {
  106. let games = await getJoinableGames(playerName);
  107. response = {
  108. res: 'ok',
  109. message: games
  110. };
  111. } catch (error) {
  112. response = {
  113. res: 'ko',
  114. message: 'Error from server'
  115. };
  116. }
  117. callback(response);
  118. });
  119. socket.on('create-game', async (game, callback) => {
  120. let response = {};
  121. try {
  122. let id = await addGameDb(game);
  123. response = {
  124. res: 'ok',
  125. message: id
  126. };
  127. gamesManager.addPlayerInGame(
  128. authorizedPlayers.get(connectedPlayers.get(socket.id)),
  129. id,
  130. false
  131. );
  132. console.log('Force all clients to reload their games');
  133. forceClientsReloadGames();
  134. } catch (error) {
  135. console.log('error in create-game:>> ', error);
  136. response = {
  137. res: 'ko',
  138. message: 'Error from server'
  139. };
  140. }
  141. callback(response);
  142. });
  143. socket.on('join-game', async (gameDetails, callback) => {
  144. let result = gamesManager.addPlayerInGame(
  145. authorizedPlayers.get(connectedPlayers.get(socket.id)),
  146. gameDetails.id,
  147. gameDetails.joinCreatedGame
  148. );
  149. let response = {};
  150. if (result === true) {
  151. response.res = 'ok';
  152. response.message = 'Game joined';
  153. } else {
  154. response.res = 'ko';
  155. response.message = 'Unable to join game';
  156. }
  157. callback(response);
  158. });
  159. socket.on('leave-game', async (username, callback) => {
  160. // Remove player from game he is playing
  161. gamesManager.playerLeft(authorizedPlayers.get(username), false);
  162. try {
  163. let res = removeAllGamesCreatedByPlayer(username);
  164. if (res.affectedRows > 0) {
  165. forceClientsReloadGames();
  166. }
  167. } catch (err) {
  168. console.log('Error removing games : ' + err.message);
  169. }
  170. callback(true);
  171. });
  172. });
  173. let updatePlayersFromDb = async function() {
  174. try {
  175. let usernames = await mariadbConn.getUsernames();
  176. authorizedPlayersNames = new Set(usernames);
  177. console.log('authorizedPlayersNames update : ', authorizedPlayersNames);
  178. authorizedPlayersNames.forEach(name => {
  179. if (!authorizedPlayers.has(name)) {
  180. console.log('New username authorized :', name);
  181. authorizedPlayers.set(name, new PlayerId(name));
  182. }
  183. });
  184. return 'ok';
  185. } catch (error) {
  186. console.log('Error getting usernames from DB : ', error);
  187. return error.Error;
  188. }
  189. };
  190. let getCurrentListAuthorizedPlayers = function() {
  191. return [...authorizedPlayersNames];
  192. };
  193. let addPlayerDb = async function(username) {
  194. console.log('add player in db : ' + username);
  195. try {
  196. let response = await mariadbConn.addPlayer(username);
  197. authorizedPlayersNames.add(username);
  198. authorizedPlayers.set(username, new PlayerId(username));
  199. return 'OK ' + JSON.stringify(response);
  200. } catch (err) {
  201. return 'KO ' + err.message;
  202. }
  203. };
  204. let removePlayerDb = async function(username) {
  205. console.log('remove player in db : ' + username);
  206. try {
  207. let response = await mariadbConn.removePlayer(username);
  208. authorizedPlayersNames.delete(username);
  209. authorizedPlayers.delete(username);
  210. return 'OK ' + JSON.stringify(response);
  211. } catch (err) {
  212. return 'KO ' + err.message;
  213. }
  214. };
  215. let addGameDb = async function(game) {
  216. try {
  217. let response = await mariadbConn.addNewGame(game);
  218. return response;
  219. } catch (err) {
  220. console.log('KO ' + err.message);
  221. throw err;
  222. }
  223. };
  224. let removeGameDb = async function(method, ...args) {
  225. try {
  226. let response;
  227. switch (method) {
  228. case 'byId':
  229. response = await mariadbConn.removeGameById(args[0]);
  230. break;
  231. case 'byPlayer1':
  232. response = await mariadbConn.removeGamesByPlayer1(args[0]);
  233. break;
  234. case 'byPlayerAny':
  235. response = await mariadbConn.removeGamesByPlayerAny(args[0]);
  236. break;
  237. case 'byStatus':
  238. response = await mariadbConn.removeGamesByStatus(args[0]);
  239. break;
  240. case 'byDays':
  241. response = await mariadbConn.removeGamesByDays(args[0]);
  242. break;
  243. case 'finishedByDays':
  244. response = await mariadbConn.removeFinishedGamesByDays(args[0]);
  245. break;
  246. default:
  247. return 'KO : Unknown method to remove game from DB : ' + method;
  248. }
  249. return 'OK ' + JSON.stringify(response);
  250. } catch (err) {
  251. return 'KO ' + err.message;
  252. }
  253. };
  254. let getJoinableGames = async function(username) {
  255. try {
  256. let games = await mariadbConn.getJoinableGamesForPlayer(username);
  257. return games;
  258. } catch (err) {
  259. console.log('KO : not able to get games : ' + err);
  260. throw err;
  261. }
  262. };
  263. let removeAllGamesCreatedByPlayer = async function(playerName) {
  264. let result = await mariadbConn.removeCreatedGamesByPlayer1(playerName);
  265. return result;
  266. };
  267. let forceClientsReloadGames = function() {
  268. server.emit('reload-games-list');
  269. };
  270. return {
  271. updatePlayersFromDb,
  272. getCurrentListAuthorizedPlayers,
  273. addPlayerDb,
  274. removePlayerDb,
  275. addGameDb,
  276. removeGameDb,
  277. getJoinableGames
  278. };
  279. }
  280. let server = new Server();
  281. let serverToolListner = new ServerToolListner(server);
  282. serverToolListner.listen(1664);