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.
 
 
 

374 lines
7.1 KiB

  1. const eventEmitter = require('../misc/events');
  2. let objBase = require('./objBase');
  3. module.exports = {
  4. lastId: 0,
  5. instance: null,
  6. objects: [],
  7. init: function (_instance) {
  8. this.instance = _instance;
  9. this.physics = this.instance.physics;
  10. },
  11. getNextId: function () {
  12. return ++this.lastId;
  13. },
  14. build: function (isClientObj, id) {
  15. let o = extend({}, objBase);
  16. if (isClientObj)
  17. o.update = null;
  18. else {
  19. o.id = id || this.getNextId();
  20. o.addComponent('syncer');
  21. o.instance = this.instance;
  22. }
  23. return o;
  24. },
  25. pushObjectToList: function (obj) {
  26. this.objects.push(obj);
  27. },
  28. transferObject: function (o) {
  29. const obj = this.build();
  30. let components = o.components;
  31. delete o.components;
  32. delete o.id;
  33. for (let p in o)
  34. obj[p] = o[p];
  35. const cLen = components.length;
  36. for (let i = 0; i < cLen; i++) {
  37. let c = components[i];
  38. const cpn = obj.addComponent(c.type, null, true);
  39. for (let p in c)
  40. cpn[p] = c[p];
  41. if (cpn.transfer)
  42. cpn.transfer();
  43. }
  44. this.pushObjectToList(obj);
  45. this.physics.addObject(obj, obj.x, obj.y);
  46. return obj;
  47. },
  48. buildObjects: function (list, skipPush) {
  49. let lLen = list.length;
  50. for (let i = 0; i < lLen; i++) {
  51. let l = list[i];
  52. let obj = this.build(l.clientObj, l.id);
  53. obj.sheetName = l.sheetName;
  54. obj.cell = l.cell;
  55. obj.name = l.name;
  56. obj.x = l.x;
  57. obj.y = l.y;
  58. if (l.ttl)
  59. obj.ttl = l.ttl;
  60. if (l.width) {
  61. obj.width = l.width;
  62. obj.height = l.height;
  63. }
  64. if (l.area)
  65. obj.area = l.area;
  66. //Add components (certain ones need to happen first)
  67. //TODO: Clean this part up
  68. let properties = extend({}, l.properties);
  69. ['cpnMob'].forEach(function (c) {
  70. let blueprint = properties[c] || null;
  71. if ((blueprint) && (typeof (blueprint) === 'string'))
  72. blueprint = JSON.parse(blueprint);
  73. if (!blueprint)
  74. return;
  75. delete properties[c];
  76. let type = c.replace('cpn', '').toLowerCase();
  77. obj.addComponent(type, blueprint);
  78. }, this);
  79. for (let p in properties) {
  80. if (p.indexOf('cpn') === -1) {
  81. obj[p] = properties[p];
  82. continue;
  83. }
  84. let type = p.replace('cpn', '');
  85. type = type[0].toLowerCase() + type.substr(1);
  86. let blueprint = properties[p] || null;
  87. if ((blueprint) && (typeof (blueprint) === 'string'))
  88. blueprint = JSON.parse(blueprint);
  89. obj.addComponent(type, blueprint);
  90. }
  91. let extraProperties = l.extraProperties || {};
  92. for (let p in extraProperties) {
  93. let cpn = obj[p];
  94. let e = extraProperties[p];
  95. for (let pp in e)
  96. cpn[pp] = e[pp];
  97. if (cpn.init)
  98. cpn.init();
  99. }
  100. if ((this.physics) && (!obj.dead)) {
  101. if (!obj.width)
  102. this.physics.addObject(obj, obj.x, obj.y);
  103. else
  104. this.physics.addRegion(obj);
  105. }
  106. if (obj.aggro)
  107. obj.aggro.move();
  108. if (!skipPush)
  109. this.pushObjectToList(obj);
  110. if (lLen === 1)
  111. return obj;
  112. }
  113. },
  114. find: function (callback) {
  115. return this.objects.find(callback);
  116. },
  117. filter: function (callback) {
  118. return this.objects.filter(callback);
  119. },
  120. removeObject: function (obj, callback, useServerId) {
  121. let found = this.objects.spliceFirstWhere(o => obj.id === (useServerId ? o.serverId : o.id));
  122. if (!found)
  123. return;
  124. let physics = this.physics;
  125. if (physics) {
  126. if (!found.width)
  127. physics.removeObject(found, found.x, found.y);
  128. else
  129. physics.removeRegion(found);
  130. }
  131. found.destroy();
  132. if (callback)
  133. callback(found);
  134. },
  135. addObject: function (o, callback) {
  136. const newO = this.build();
  137. const components = o.components;
  138. delete o.components;
  139. for (let p in o)
  140. newO[p] = o[p];
  141. const len = components.length;
  142. for (let i = 0; i < len; i++) {
  143. const c = components[i];
  144. const newC = newO.addComponent(c.type, c);
  145. extend(newC, c);
  146. }
  147. this.pushObjectToList(newO);
  148. if (!newO.dead)
  149. this.physics.addObject(newO, newO.x, newO.y);
  150. callback(newO);
  151. return newO;
  152. },
  153. sendEvent: function (msg, { name: sourceZone }) {
  154. const { id, data } = msg;
  155. const player = this.objects.find(p => p.id === id);
  156. if (!player || player.zoneName !== sourceZone)
  157. return;
  158. player.socket.emit('event', {
  159. event: data.event,
  160. data: data.data
  161. });
  162. },
  163. sendEvents: function ({ data }, { name: sourceZone }) {
  164. const { objects } = this;
  165. //Store will contain all events to be sent to players
  166. const store = {};
  167. for (let e in data) {
  168. const event = data[e];
  169. const eLen = event.length;
  170. for (let j = 0; j < eLen; j++) {
  171. const eventEntry = event[j];
  172. const { obj: eventObj, to } = eventEntry;
  173. if (e === 'serverModule') {
  174. const { method, msg } = eventObj;
  175. if (Array.isArray(msg))
  176. global[eventObj.module][method](...msg);
  177. else
  178. global[eventObj.module][method](msg);
  179. continue;
  180. }
  181. const toLen = to.length;
  182. for (let i = 0; i < toLen; i++) {
  183. const toId = to[i];
  184. let storeEntry = store[toId];
  185. if (!storeEntry) {
  186. const playerObj = objects.find(o => o.id === toId);
  187. if (!playerObj || playerObj.zoneName !== sourceZone)
  188. continue;
  189. store[toId] = {
  190. obj: playerObj,
  191. events: { [e]: [eventObj] }
  192. };
  193. continue;
  194. }
  195. if (!storeEntry.events[e])
  196. storeEntry.events[e] = [];
  197. storeEntry.events[e].push(eventObj);
  198. }
  199. }
  200. }
  201. for (let p in store) {
  202. const { obj: { socket }, events } = store[p];
  203. socket.emit('events', events);
  204. }
  205. },
  206. updateObject: async function (msg) {
  207. let player = this.objects.find(p => p.id === msg.serverId);
  208. if (!player)
  209. return;
  210. let obj = msg.obj;
  211. for (let p in obj)
  212. player[p] = obj[p];
  213. if (obj.permadead)
  214. await leaderboard.killCharacter(player.name);
  215. if (obj.level) {
  216. await leaderboard.setLevel(player.name, obj.level);
  217. player.components.find(c => c.type === 'stats').values.level = obj.level;
  218. cons.emit('events', {
  219. onGetMessages: [{
  220. messages: [{
  221. class: 'color-blueB',
  222. message: player.name + ' has reached level ' + obj.level
  223. }]
  224. }]
  225. });
  226. eventEmitter.emit('playerObjChanged', {
  227. obj: player
  228. });
  229. }
  230. },
  231. notifyCollisionChange: function (x, y, collides) {
  232. this.objects
  233. .filter(o => o.player)
  234. .forEach(function (o) {
  235. o.syncer.setArray(true, 'player', 'collisionChanges', {
  236. x,
  237. y,
  238. collides
  239. });
  240. });
  241. },
  242. notifyMapChange: function (x, y, mapCellString) {
  243. this.objects
  244. .filter(o => o.player)
  245. .forEach(function (o) {
  246. o.syncer.setArray(true, 'player', 'mapChanges', {
  247. x,
  248. y,
  249. mapCellString
  250. });
  251. });
  252. },
  253. update: function () {
  254. let objects = this.objects;
  255. let len = objects.length;
  256. for (let i = 0; i < len; i++) {
  257. let o = objects[i];
  258. //If object A causes object B (layer in the list) to rezone, we won't find it here
  259. if (!o) {
  260. len--;
  261. continue;
  262. }
  263. //Don't remove it from the list if it's destroyed, but don't update it either
  264. //That's syncer's job
  265. if ((o.update) && (!o.destroyed))
  266. o.update();
  267. //When objects are sent to other zones, we destroy them immediately (thhrough sendObjToZone)
  268. if (o.forceDestroy) {
  269. i--;
  270. len--;
  271. continue;
  272. }
  273. if (o.ttl) {
  274. o.ttl--;
  275. if (!o.ttl)
  276. o.destroyed = true;
  277. }
  278. o.fireEvent('afterTick');
  279. }
  280. }
  281. };