You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

202 lines
4.0 KiB

  1. //External Modules
  2. const objects = require('../objects/objects');
  3. //Helpers
  4. const { route, routeGlobal } = require('./connections/route');
  5. //Module
  6. module.exports = {
  7. players: [],
  8. sockets: null,
  9. playing: 0,
  10. onHandshake: function (socket) {
  11. if (this.players.some(f => f.socket.id === socket.id))
  12. return;
  13. const p = objects.build();
  14. p.socket = socket;
  15. p.addComponent('auth');
  16. p.addComponent('player');
  17. objects.pushObjectToList(p);
  18. this.players.push(p);
  19. },
  20. onDisconnect: async function (socket) {
  21. let player = this.players.find(p => p.socket.id === socket.id);
  22. if (!player)
  23. return;
  24. let sessionDuration = 0;
  25. if (player.has('id')) {
  26. if (player.social)
  27. player.social.dc();
  28. sessionDuration = ~~(((+new Date()) - player.player.sessionStart) / 1000);
  29. atlas.updateObject(player, {
  30. components: [{
  31. type: 'stats',
  32. sessionDuration: sessionDuration
  33. }]
  34. });
  35. //If the player doesn't have a 'social' component, they are no longer in a threat
  36. // Likely due to unzoning (character select screen)
  37. if (player.components.some(c => c.type === 'social')) {
  38. await new Promise(res => {
  39. atlas.removeObject(player, false, res);
  40. });
  41. }
  42. }
  43. if (player.name) {
  44. this.emit('events', {
  45. onGetMessages: [{
  46. messages: [{
  47. class: 'color-blueB',
  48. message: player.name + ' has gone offline'
  49. }]
  50. }],
  51. onGetDisconnectedPlayer: [player.name]
  52. });
  53. if (player.has('id'))
  54. this.modifyPlayerCount(-1);
  55. }
  56. this.players.spliceWhere(p => p.socket.id === socket.id);
  57. },
  58. route: function (socket, msg) {
  59. route.call(this, socket, msg);
  60. },
  61. routeGlobal: function (msg) {
  62. routeGlobal.call(this, msg);
  63. },
  64. unzone: async function (msg) {
  65. let socket = msg.socket;
  66. let player = this.players.find(p => p.socket.id === socket.id);
  67. if (!player)
  68. return;
  69. if (player.social)
  70. player.social.dc();
  71. await new Promise(res => {
  72. atlas.removeObject(player, true, res);
  73. });
  74. let keys = Object.keys(player);
  75. keys.forEach(function (k) {
  76. let val = player[k];
  77. if (val && val.type) {
  78. if (['player', 'auth', 'syncer'].indexOf(val.type) === -1) {
  79. delete player[k];
  80. player.components.spliceWhere(c => c.type === val.type);
  81. }
  82. }
  83. });
  84. this.emit('events', {
  85. onGetMessages: [{
  86. messages: [{
  87. class: 'color-blueB',
  88. message: player.name + ' has gone offline'
  89. }]
  90. }],
  91. onGetDisconnectedPlayer: [player.name]
  92. });
  93. //If we don't do this, the atlas will try to remove it from the thread
  94. delete player.zoneName;
  95. delete player.name;
  96. //A hack to allow us to actually call methods again (like retrieve the player list)
  97. player.dead = false;
  98. player.permadead = false;
  99. delete player.auth.charname;
  100. this.modifyPlayerCount(-1);
  101. msg.callback();
  102. },
  103. logOut: async function (exclude) {
  104. let players = this.players;
  105. let pLen = players.length;
  106. for (let i = 0; i < pLen; i++) {
  107. let p = players[i];
  108. if ((!p) || (p === exclude) || (!p.auth))
  109. continue;
  110. if (p.auth.username === exclude.auth.username) {
  111. if (p.name && p.zoneId)
  112. await atlas.forceSavePlayer(p.id, p.zoneId);
  113. p.socket.emit('dc', {});
  114. }
  115. }
  116. },
  117. emit: function (event, msg) {
  118. this.sockets.emit(event, msg);
  119. },
  120. getCharacterList: function () {
  121. let result = [];
  122. let players = this.players;
  123. let pLen = players.length;
  124. for (let i = 0; i < pLen; i++) {
  125. let p = players[i];
  126. if (!p.name)
  127. continue;
  128. result.push({
  129. zoneName: p.zoneName,
  130. zoneId: p.zoneId,
  131. name: p.name,
  132. level: p.level,
  133. class: p.class,
  134. id: p.id
  135. });
  136. }
  137. return result;
  138. },
  139. forceSaveAll: async function () {
  140. const promises = this.players
  141. .filter(p => p.zoneName !== undefined)
  142. .map(p => {
  143. const promise = new Promise(res => {
  144. const msg = {
  145. cpn: 'auth',
  146. method: 'doSaveManual',
  147. data: {
  148. callbackId: atlas.registerCallback(res)
  149. }
  150. };
  151. atlas.performAction(p, msg);
  152. });
  153. return promise;
  154. });
  155. await Promise.all(promises);
  156. },
  157. modifyPlayerCount: function (delta) {
  158. this.playing += delta;
  159. }
  160. };