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.
 
 
 

205 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. //Rezoning is set to true while rezoning so we don't try to remove objects
  36. // from zones if they are currently rezoning
  37. if (player.rezoning !== true) {
  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. }
  81. });
  82. this.emit('events', {
  83. onGetMessages: [{
  84. messages: [{
  85. class: 'color-blueB',
  86. message: player.name + ' has gone offline'
  87. }]
  88. }],
  89. onGetDisconnectedPlayer: [player.name]
  90. });
  91. //If we don't do this, the atlas will try to remove it from the thread
  92. delete player.zoneName;
  93. delete player.name;
  94. //A hack to allow us to actually call methods again (like retrieve the player list)
  95. player.dead = false;
  96. player.permadead = false;
  97. delete player.auth.charname;
  98. this.modifyPlayerCount(-1);
  99. msg.callback();
  100. },
  101. logOut: async function (exclude) {
  102. const { players } = this;
  103. let pLen = players.length;
  104. for (let i = 0; i < pLen; i++) {
  105. const p = players[i];
  106. if (!p || p === exclude || !p.auth)
  107. continue;
  108. else if (p.auth.username === exclude.auth.username) {
  109. if (p.name && p.zoneId)
  110. await atlas.forceSavePlayer(p.id, p.zoneId);
  111. if (p.socket?.connected)
  112. p.socket.emit('dc', {});
  113. else {
  114. players.splice(i, 1);
  115. i--;
  116. pLen--;
  117. }
  118. }
  119. }
  120. },
  121. emit: function (event, msg) {
  122. this.sockets.emit(event, msg);
  123. },
  124. getCharacterList: function () {
  125. let result = [];
  126. let players = this.players;
  127. let pLen = players.length;
  128. for (let i = 0; i < pLen; i++) {
  129. let p = players[i];
  130. if (!p.name)
  131. continue;
  132. result.push({
  133. zoneName: p.zoneName,
  134. zoneId: p.zoneId,
  135. name: p.name,
  136. level: p.level,
  137. class: p.class,
  138. id: p.id
  139. });
  140. }
  141. return result;
  142. },
  143. forceSaveAll: async function () {
  144. const promises = this.players
  145. .filter(p => p.zoneName !== undefined)
  146. .map(p => {
  147. const promise = new Promise(res => {
  148. const msg = {
  149. cpn: 'auth',
  150. method: 'doSaveManual',
  151. data: {
  152. callbackId: atlas.registerCallback(res)
  153. }
  154. };
  155. atlas.performAction(p, msg);
  156. });
  157. return promise;
  158. });
  159. await Promise.all(promises);
  160. },
  161. modifyPlayerCount: function (delta) {
  162. this.playing += delta;
  163. }
  164. };