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.
 
 
 

200 lines
3.9 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. await new Promise(res => {
  36. atlas.removeObject(player, false, res);
  37. });
  38. }
  39. if (player.name) {
  40. this.emit('events', {
  41. onGetMessages: [{
  42. messages: [{
  43. class: 'color-blueB',
  44. message: player.name + ' has gone offline'
  45. }]
  46. }],
  47. onGetDisconnectedPlayer: [player.name]
  48. });
  49. if (player.has('id'))
  50. this.modifyPlayerCount(-1);
  51. }
  52. this.players.spliceWhere(p => p.socket.id === socket.id);
  53. },
  54. route: function (socket, msg) {
  55. route.call(this, socket, msg);
  56. },
  57. routeGlobal: function (msg) {
  58. routeGlobal.call(this, msg);
  59. },
  60. unzone: async function (msg) {
  61. let socket = msg.socket;
  62. let player = this.players.find(p => p.socket.id === socket.id);
  63. if (!player)
  64. return;
  65. if (player.social)
  66. player.social.dc();
  67. await new Promise(res => {
  68. atlas.removeObject(player, true, res);
  69. });
  70. let keys = Object.keys(player);
  71. keys.forEach(function (k) {
  72. let val = player[k];
  73. if (val && val.type) {
  74. if (['player', 'auth', 'syncer'].indexOf(val.type) === -1) {
  75. delete player[k];
  76. player.components.spliceWhere(c => c.type === val.type);
  77. }
  78. }
  79. });
  80. this.emit('events', {
  81. onGetMessages: [{
  82. messages: [{
  83. class: 'color-blueB',
  84. message: player.name + ' has gone offline'
  85. }]
  86. }],
  87. onGetDisconnectedPlayer: [player.name]
  88. });
  89. //If we don't do this, the atlas will try to remove it from the thread
  90. delete player.zoneName;
  91. delete player.name;
  92. delete player.zoneId;
  93. //A hack to allow us to actually call methods again (like retrieve the player list)
  94. player.dead = false;
  95. player.permadead = false;
  96. delete player.auth.charname;
  97. player.id = objects.getNextId();
  98. this.modifyPlayerCount(-1);
  99. msg.callback();
  100. },
  101. logOut: async function (exclude) {
  102. let players = this.players;
  103. let pLen = players.length;
  104. for (let i = 0; i < pLen; i++) {
  105. let p = players[i];
  106. if ((!p) || (p === exclude) || (!p.auth))
  107. continue;
  108. if (p.auth.username === exclude.auth.username) {
  109. if (p.name && p.zoneId)
  110. await atlas.forceSavePlayer(p.id, p.zoneId);
  111. p.socket.emit('dc', {});
  112. }
  113. }
  114. },
  115. emit: function (event, msg) {
  116. this.sockets.emit(event, msg);
  117. },
  118. getCharacterList: function () {
  119. let result = [];
  120. let players = this.players;
  121. let pLen = players.length;
  122. for (let i = 0; i < pLen; i++) {
  123. let p = players[i];
  124. if (!p.name)
  125. continue;
  126. result.push({
  127. zoneName: p.zoneName,
  128. zoneId: p.zoneId,
  129. name: p.name,
  130. level: p.level,
  131. class: p.class,
  132. id: p.id
  133. });
  134. }
  135. return result;
  136. },
  137. forceSaveAll: async function () {
  138. const promises = this.players
  139. .filter(p => p.zoneName !== undefined)
  140. .map(p => {
  141. const promise = new Promise(res => {
  142. const msg = {
  143. cpn: 'auth',
  144. method: 'doSaveManual',
  145. data: {
  146. callbackId: atlas.registerCallback(res)
  147. }
  148. };
  149. atlas.performAction(p, msg);
  150. });
  151. return promise;
  152. });
  153. await Promise.all(promises);
  154. },
  155. modifyPlayerCount: function (delta) {
  156. this.playing += delta;
  157. }
  158. };