io.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /**
  2. * Socket.IO
  3. */
  4. var io = require('socket.io').listen();
  5. var winston = require('./winston');
  6. var games = {};
  7. var timer;
  8. io.sockets.on('connection', function (socket) {
  9. socket.on('start', function (data) {
  10. var token;
  11. var b = new Buffer(Math.random() + new Date().getTime() + socket.id);
  12. token = b.toString('base64').slice(12, 32);
  13. // token is valid for 5 minutes
  14. var timeout = setTimeout(function () {
  15. if (games[token].players.length === 0) {
  16. delete games[token];
  17. socket.emit('token-expired');
  18. }
  19. }, 5 * 60 * 1000);
  20. games[token] = {
  21. 'creator': socket,
  22. 'players': [],
  23. 'interval': null,
  24. 'timeout': timeout
  25. };
  26. socket.emit('created', {
  27. 'token': token
  28. });
  29. });
  30. socket.on('join', function (data) {
  31. var game, color, time = data.time;
  32. if (!(data.token in games)) {
  33. socket.emit('token-invalid');
  34. return;
  35. }
  36. clearTimeout(games[data.token].timeout);
  37. game = games[data.token];
  38. if (game.players.length >= 2) {
  39. socket.emit('full');
  40. return;
  41. } else if (game.players.length === 1) {
  42. if (game.players[0].color === 'black') {
  43. color = 'white';
  44. } else {
  45. color = 'black';
  46. }
  47. winston.log('info', 'Number of currently running games', { '#': Object.keys(games).length });
  48. } else {
  49. var colors = ['black', 'white'];
  50. color = colors[Math.floor(Math.random() * 2)];
  51. }
  52. // join room
  53. socket.join(data.token);
  54. games[data.token].players.push({
  55. 'id': socket.id,
  56. 'socket': socket,
  57. 'color': color,
  58. 'time': data.time - data.increment + 1,
  59. 'increment': data.increment
  60. });
  61. game.creator.emit('ready', {});
  62. socket.emit('joined', {
  63. 'color': color
  64. });
  65. });
  66. socket.on('timer-white', function (data) {
  67. runTimer('white', data.token, socket);
  68. });
  69. socket.on('timer-black', function (data) {
  70. runTimer('black', data.token, socket);
  71. });
  72. socket.on('timer-clear-interval', function (data) {
  73. if (data.token in games) {
  74. clearInterval(games[data.token].interval);
  75. }
  76. });
  77. socket.on('new-move', function (data) {
  78. var opponent;
  79. if (data.token in games) {
  80. opponent = getOpponent(data.token, socket);
  81. if (opponent) {
  82. opponent.socket.emit('move', {
  83. 'move': data.move
  84. });
  85. }
  86. }
  87. });
  88. socket.on('resign', function (data) {
  89. if (data.token in games) {
  90. clearInterval(games[data.token].interval);
  91. io.sockets.in(data.token).emit('player-resigned', {
  92. 'color': data.color
  93. });
  94. }
  95. });
  96. socket.on('rematch-offer', function (data) {
  97. var opponent;
  98. if (data.token in games) {
  99. opponent = getOpponent(data.token, socket);
  100. if (opponent) {
  101. opponent.socket.emit('rematch-offered');
  102. }
  103. }
  104. });
  105. socket.on('rematch-decline', function (data) {
  106. var opponent;
  107. if (data.token in games) {
  108. opponent = getOpponent(data.token, socket);
  109. if (opponent) {
  110. opponent.socket.emit('rematch-declined');
  111. }
  112. }
  113. });
  114. socket.on('rematch-confirm', function (data) {
  115. var opponent;
  116. if (data.token in games) {
  117. for(var j in games[data.token].players) {
  118. games[data.token].players[j].time = data.time - data.increment + 1;
  119. games[data.token].players[j].increment = data.increment;
  120. games[data.token].players[j].color = games[data.token].players[j].color === 'black' ? 'white' : 'black';
  121. }
  122. opponent = getOpponent(data.token, socket);
  123. if (opponent) {
  124. io.sockets.in(data.token).emit('rematch-confirmed');
  125. }
  126. }
  127. });
  128. socket.on('disconnect', function (data) {
  129. var player, opponent, game;
  130. for (var token in games) {
  131. game = games[token];
  132. for (var j in game.players) {
  133. player = game.players[j];
  134. if (player.socket === socket) {
  135. opponent = game.players[Math.abs(j - 1)];
  136. if (opponent) {
  137. opponent.socket.emit('opponent-disconnected');
  138. }
  139. clearInterval(games[token].interval);
  140. delete games[token];
  141. }
  142. }
  143. }
  144. });
  145. socket.on('send-message', function (data) {
  146. if (data.token in games) {
  147. var opponent = getOpponent(data.token, socket);
  148. if (opponent) {
  149. opponent.socket.emit('receive-message', data);
  150. }
  151. }
  152. });
  153. });
  154. function runTimer(color, token, socket) {
  155. var player, time_left, game = games[token];
  156. if (!game) return;
  157. for (var i in game.players) {
  158. player = game.players[i];
  159. if (player.socket === socket && player.color === color) {
  160. clearInterval(games[token].interval);
  161. games[token].players[i].time += games[token].players[i].increment;
  162. return games[token].interval = setInterval(function() {
  163. games[token].players[i].time -= 1;
  164. time_left = games[token].players[i].time;
  165. if (time_left >= 0) {
  166. io.sockets.in(token).emit('countdown', {
  167. 'time': time_left,
  168. 'color': color
  169. });
  170. } else {
  171. io.sockets.in(token).emit('countdown-gameover', {
  172. 'color': color
  173. });
  174. clearInterval(games[token].interval);
  175. }
  176. }, 1000);
  177. }
  178. }
  179. }
  180. function getOpponent(token, socket) {
  181. var player, game = games[token];
  182. for (var j in game.players) {
  183. player = game.players[j];
  184. if (player.socket === socket) {
  185. var opponent = game.players[Math.abs(j - 1)];
  186. return opponent;
  187. }
  188. }
  189. }
  190. module.exports = io;