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.
 
 
 

255 lines
4.7 KiB

  1. const { viewDistanceX, viewDistanceY } = consts;
  2. module.exports = {
  3. buffer: {},
  4. dirty: false,
  5. init: function (msg) {
  6. this.objects = msg.objects;
  7. },
  8. update: function () {
  9. let objects = this.objects;
  10. let oList = objects.objects;
  11. let oLen = oList.length;
  12. let pList = oList.filter(f => f.player && !f.destroyed);
  13. let pLen = pList.length;
  14. if (pLen === 0)
  15. this.updateZoneEmpty(objects, oList, oLen);
  16. else if (pLen > 0)
  17. this.updateZoneNotEmpty(objects, oList, oLen, pList, pLen);
  18. oLen = oList.length;
  19. for (let i = 0; i < oList.length; i++)
  20. oList[i].syncer.reset();
  21. },
  22. updateZoneEmpty: function (objects, oList, oLen) {
  23. for (let i = 0; i < oLen; i++) {
  24. let o = oList[i];
  25. if (!o.destroyed)
  26. continue;
  27. objects.removeObject(o);
  28. oLen--;
  29. i--;
  30. }
  31. this.sendServerModuleMessages();
  32. },
  33. updateZoneNotEmpty: function (objects, oList, oLen, pList, pLen) {
  34. let queueFunction = this.queue.bind(this, 'onGetObject');
  35. let cache = {};
  36. for (let i = 0; i < oLen; i++) {
  37. let o = oList[i];
  38. let canBeSeenBy = o.canBeSeenBy;
  39. let oId = o.id;
  40. let ox = o.x;
  41. let oy = o.y;
  42. if (!o.syncer)
  43. continue;
  44. let destroyed = o.destroyed;
  45. let sync = null;
  46. let syncSelf = null;
  47. if (!destroyed) {
  48. sync = o.syncer.get();
  49. syncSelf = o.syncer.get(true);
  50. o.syncer.locked = true;
  51. } else {
  52. sync = {
  53. id: o.id,
  54. destroyed: true,
  55. destructionEvent: o.destructionEvent
  56. };
  57. objects.removeObject(o);
  58. oLen--;
  59. i--;
  60. }
  61. let toList = [];
  62. let completeList = [];
  63. let completeObj = null;
  64. let sendTo = false;
  65. let sendComplete = false;
  66. for (let j = 0; j < pLen; j++) {
  67. let p = pList[j];
  68. let px = p.x;
  69. let py = p.y;
  70. const canSee = (
  71. Math.abs(ox - px) <= viewDistanceX && Math.abs(oy - py) < viewDistanceY &&
  72. (
  73. !canBeSeenBy ||
  74. canBeSeenBy === p.name
  75. )
  76. );
  77. let hasSeen = p.player.hasSeen(oId);
  78. if (hasSeen) {
  79. if (canSee) {
  80. if (p.id === oId && syncSelf)
  81. queueFunction(syncSelf, [ p.serverId ]);
  82. if (sync) {
  83. toList.push(p.serverId);
  84. sendTo = true;
  85. }
  86. }
  87. if (destroyed || !canSee) {
  88. if (!canSee) {
  89. queueFunction({
  90. id: oId,
  91. destroyed: true,
  92. destructionEvent: 'visibility'
  93. },
  94. [ p.serverId ]);
  95. }
  96. p.player.unsee(oId);
  97. }
  98. } else if (!destroyed && canSee) {
  99. let cached = null;
  100. if (p.id === oId) {
  101. let syncO = o.getSimple(true);
  102. syncO.self = true;
  103. queueFunction(syncO, [ p.serverId ]);
  104. p.player.see(oId);
  105. continue;
  106. } else {
  107. cached = cache[oId];
  108. if (!cached)
  109. cached = cache[oId] = o.getSimple();
  110. }
  111. completeObj = cached;
  112. completeList.push(p.serverId);
  113. sendComplete = true;
  114. p.player.see(oId);
  115. }
  116. }
  117. if (sendTo)
  118. queueFunction(sync, toList);
  119. if (sendComplete)
  120. queueFunction(completeObj, completeList);
  121. }
  122. this.send();
  123. },
  124. queue: function (event, obj, to) {
  125. //Send to all players in zone?
  126. if (to === -1) {
  127. let pList = this.objects.objects.filter(o => o.player);
  128. to = pList.map(p => p.serverId);
  129. }
  130. if (!to.length)
  131. return;
  132. this.dirty = true;
  133. let buffer = this.buffer;
  134. let list = buffer[event] || (buffer[event] = []);
  135. list.push({
  136. to: to,
  137. obj: obj
  138. });
  139. },
  140. flushForTarget: function (targetServerId) {
  141. const buffer = this.buffer;
  142. for (let p in buffer) {
  143. const list = buffer[p];
  144. list.forEach(l => l.to.spliceWhere(f => f === targetServerId));
  145. list.spliceWhere(l => !l.to.length);
  146. if (!list.length)
  147. delete buffer[p];
  148. }
  149. },
  150. processDestroyedObject: function (obj) {
  151. const { objects, queue } = this;
  152. const { id, serverId } = obj;
  153. obj.destroyed = true;
  154. //We mark forceDestroy to tell objects that we're destroying an object outside of the
  155. // syncer's update method
  156. obj.forceDestroy = true;
  157. const msg = {
  158. id: id,
  159. destroyed: true
  160. };
  161. objects.removeObject(obj);
  162. this.flushForTarget(serverId);
  163. const fnQueueMsg = queue.bind(this, 'onGetObject');
  164. //Find any players that have seen this obj
  165. objects
  166. .filter(o => !o.destroyed && o?.player?.hasSeen(id))
  167. .forEach(o => {
  168. fnQueueMsg(msg, [o.serverId]);
  169. });
  170. },
  171. send: function () {
  172. if (!this.dirty)
  173. return;
  174. this.dirty = false;
  175. process.send({
  176. method: 'events',
  177. data: this.buffer
  178. });
  179. this.buffer = {};
  180. },
  181. sendServerModuleMessages: function () {
  182. if (!this.dirty)
  183. return;
  184. this.dirty = false;
  185. const serverModuleMsgs = this.buffer.serverModule;
  186. if (serverModuleMsgs) {
  187. process.send({
  188. method: 'events',
  189. data: {
  190. serverModule: serverModuleMsgs
  191. }
  192. });
  193. }
  194. this.buffer = {};
  195. }
  196. };