server.js 8.9 KB

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