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.
 
 
 

199 lines
4.1 KiB

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