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.
 
 
 

204 lines
4.1 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. delete player.zoneId;
  97. //A hack to allow us to actually call methods again (like retrieve the player list)
  98. player.dead = false;
  99. player.permadead = false;
  100. delete player.auth.charname;
  101. player.id = objects.getNextId();
  102. this.modifyPlayerCount(-1);
  103. msg.callback();
  104. },
  105. logOut: async function (exclude) {
  106. let players = this.players;
  107. let pLen = players.length;
  108. for (let i = 0; i < pLen; i++) {
  109. let p = players[i];
  110. if ((!p) || (p === exclude) || (!p.auth))
  111. continue;
  112. if (p.auth.username === exclude.auth.username) {
  113. if (p.name && p.zoneId)
  114. await atlas.forceSavePlayer(p.id, p.zoneId);
  115. p.socket.emit('dc', {});
  116. }
  117. }
  118. },
  119. emit: function (event, msg) {
  120. this.sockets.emit(event, msg);
  121. },
  122. getCharacterList: function () {
  123. let result = [];
  124. let players = this.players;
  125. let pLen = players.length;
  126. for (let i = 0; i < pLen; i++) {
  127. let p = players[i];
  128. if (!p.name)
  129. continue;
  130. result.push({
  131. zoneName: p.zoneName,
  132. zoneId: p.zoneId,
  133. name: p.name,
  134. level: p.level,
  135. class: p.class,
  136. id: p.id
  137. });
  138. }
  139. return result;
  140. },
  141. forceSaveAll: async function () {
  142. const promises = this.players
  143. .filter(p => p.zoneName !== undefined)
  144. .map(p => {
  145. const promise = new Promise(res => {
  146. const msg = {
  147. cpn: 'auth',
  148. method: 'doSaveManual',
  149. data: {
  150. callbackId: atlas.registerCallback(res)
  151. }
  152. };
  153. atlas.performAction(p, msg);
  154. });
  155. return promise;
  156. });
  157. await Promise.all(promises);
  158. },
  159. modifyPlayerCount: function (delta) {
  160. this.playing += delta;
  161. }
  162. };