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.
 
 
 

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