Browse Source

Merge branch '1866-rezone-handshakes' into 'master'

feat #1866: Rebuilt rezone logic to use handshakes

Closes #1866

See merge request Isleward/isleward!575
tags/v0.10.6^2
Big Bad Waffle 2 years ago
parent
commit
2f7cafffcd
28 changed files with 446 additions and 150 deletions
  1. +13
    -2
      src/client/js/misc/physics.js
  2. +1
    -1
      src/client/js/objects/objBase.js
  3. +14
    -16
      src/client/js/objects/objects.js
  4. +45
    -0
      src/client/js/rendering/helpers/resetRenderer.js
  5. +5
    -2
      src/client/js/rendering/renderer.js
  6. +82
    -24
      src/client/js/system/client.js
  7. +2
    -2
      src/client/ui/templates/death/death.js
  8. +2
    -2
      src/client/ui/templates/events/events.js
  9. +4
    -2
      src/client/ui/templates/mainMenu/mainMenu.js
  10. +2
    -2
      src/client/ui/templates/quests/quests.js
  11. +1
    -5
      src/client/ui/templates/talk/talk.js
  12. +3
    -1
      src/server/.eslintrc
  13. +0
    -8
      src/server/clientComponents/gatherer.js
  14. +4
    -4
      src/server/clientComponents/pather.js
  15. +2
    -2
      src/server/clientComponents/player.js
  16. +1
    -1
      src/server/components/player.js
  17. +32
    -19
      src/server/components/portal/sendObjToZone.js
  18. +3
    -0
      src/server/components/social/rezone.js
  19. +2
    -2
      src/server/events/phases/phaseGiveRewards.js
  20. +67
    -43
      src/server/objects/objects.js
  21. +3
    -1
      src/server/security/routerConfig.js
  22. +2
    -2
      src/server/world/atlas.js
  23. +20
    -8
      src/server/world/instancer.js
  24. +49
    -0
      src/server/world/instancer/handshakes.js
  25. +55
    -0
      src/server/world/rezoneManager.js
  26. +0
    -1
      src/server/world/spawners.js
  27. +29
    -0
      src/server/world/syncer.js
  28. +3
    -0
      src/server/world/worker.js

+ 13
- 2
src/client/js/misc/physics.js View File

@@ -1,7 +1,9 @@
define([
'js/misc/distanceToPolygon'
'js/misc/distanceToPolygon',
'js/system/events'
], function (
distanceToPolygon
distanceToPolygon,
events
) {
return {
grid: null,
@@ -10,6 +12,8 @@ define([
height: 0,

init: function (collisionMap) {
events.on('resetPhysics', this.reset.bind(this));

this.width = collisionMap.length;
this.height = collisionMap[0].length;

@@ -22,6 +26,13 @@ define([
}
},

reset: function () {
this.width = 0;
this.height = 0;

this.grid = [];
},

isTileBlocking: function (x, y, mob, obj) {
if ((x < 0) || (y < 0) || (x >= this.width) | (y >= this.height))
return true;


+ 1
- 1
src/client/js/objects/objBase.js View File

@@ -174,7 +174,7 @@ define([

offEvents: function () {
if (this.pather)
this.pather.onDeath();
this.pather.resetPath();

for (let e in this.eventCallbacks)
this.eventCallbacks[e].forEach(c => events.off(e, c));


+ 14
- 16
src/client/js/objects/objects.js View File

@@ -15,11 +15,15 @@ define([
objects: [],

init: function () {
events.on('onGetObject', this.onGetObject.bind(this));
events.on('onRezone', this.onRezone.bind(this));
events.on('onChangeHoverTile', this.getLocation.bind(this));
events.on('onTilesVisible', this.onTilesVisible.bind(this));
events.on('onToggleNameplates', this.onToggleNameplates.bind(this));

[
'onGetObject',
'onTilesVisible',
'onToggleNameplates',
'destroyAllObjects'
]
.forEach(e => events.on(e, this[e].bind(this)));
},

getLocation: function (x, y) {
@@ -87,20 +91,14 @@ define([
return list[fromIndex];
},

onRezone: function (oldZone) {
let objects = this.objects;
let oLen = objects.length;
for (let i = 0; i < oLen; i++) {
let o = objects[i];
destroyAllObjects: function () {
this.objects.forEach(o => {
o.destroy();
});

if (oldZone === null)
o.destroy();
else if (o.zoneId === oldZone)
o.destroy();
}
this.objects.length = 0;

if (window.player)
window.player.offEvents();
window?.player?.offEvents();
},

onGetObject: function (obj) {


+ 45
- 0
src/client/js/rendering/helpers/resetRenderer.js View File

@@ -0,0 +1,45 @@
define([
'js/rendering/spritePool'
], function (
spritePool
) {
return function () {
let map = this.map;
let w = this.w = map.length;
let h = this.h = map[0].length;

this.stage.removeChild(this.layers.hiders);
this.layers.hiders = new PIXI.Container();
this.layers.hiders.layer = 'hiders';
this.stage.addChild(this.layers.hiders);

let container = this.layers.tileSprites;
this.stage.removeChild(container);

this.layers.tileSprites = container = new PIXI.Container();
container.layer = 'tiles';
this.stage.addChild(container);

this.stage.children.sort((a, b) => {
if (a.layer === 'hiders')
return 1;
else if (b.layer === 'hiders')
return -1;
else if (a.layer === 'tiles')
return -1;
else if (b.layer === 'tiles')
return 1;
return 0;
});

spritePool.clean();

this.sprites = _.get2dArray(w, h, 'array');

this.map = [];
this.w = 0;
this.h = 0;

delete this.moveTo;
};
});

+ 5
- 2
src/client/js/rendering/renderer.js View File

@@ -8,7 +8,8 @@ define([
'js/rendering/shaders/outline',
'js/rendering/spritePool',
'js/system/globals',
'js/rendering/renderLoginBackground'
'js/rendering/renderLoginBackground',
'js/rendering/helpers/resetRenderer'
], function (
resources,
events,
@@ -19,7 +20,8 @@ define([
shaderOutline,
spritePool,
globals,
renderLoginBackground
renderLoginBackground,
resetRenderer
) {
const mRandom = Math.random.bind(Math);

@@ -84,6 +86,7 @@ define([
events.on('onGetMap', this.onGetMap.bind(this));
events.on('onToggleFullscreen', this.toggleScreen.bind(this));
events.on('onMoveSpeedChange', this.adaptCameraMoveSpeed.bind(this));
events.on('resetRenderer', resetRenderer.bind(this));

this.width = $('body').width();
this.height = $('body').height();


+ 82
- 24
src/client/js/system/client.js View File

@@ -18,7 +18,38 @@ define([
this.socket.on('event', this.onEvent.bind(this));
this.socket.on('events', this.onEvents.bind(this));
this.socket.on('dc', this.onDisconnect.bind(this));

Object.entries(this.processAction).forEach(([k, v]) => {
this.processAction[k] = v.bind(this);
});
},

onRezoneStart: function () {
//Fired for mods to listen to
events.emit('rezoneStart');

events.emit('destroyAllObjects');
events.emit('resetRenderer');
events.emit('resetPhysics');
events.emit('clearUis');

client.request({
threadModule: 'rezoneManager',
method: 'clientAck',
data: {}
});
},

onGetMap: function ([msg]) {
events.emit('onGetMap', msg);

client.request({
threadModule: 'instancer',
method: 'clientAck',
data: {}
});
},

onConnected: function (onReady) {
if (this.doneConnect)
this.onDisconnect();
@@ -28,45 +59,72 @@ define([
if (onReady)
onReady();
},

onDisconnect: function () {
window.location = window.location;
},

onHandshake: function () {
events.emit('onHandshake');
this.socket.emit('handshake');
},

request: function (msg) {
this.socket.emit('request', msg, msg.callback);
},
onEvent: function (response) {
events.emit(response.event, response.data);
},
onEvents: function (response) {
//If we get objects, self needs to be first
// otherwise we might create the object (setting his position or attack animation)
// before instantiating it
let oList = response.onGetObject;
if (oList) {
let prepend = oList.filter(o => o.self);
oList.spliceWhere(o => prepend.some(p => p === o));
oList.unshift.apply(oList, prepend);
}

for (let e in response) {
let r = response[e];
processAction: {
default: function (eventName, msgs) {
msgs.forEach(m => events.emit(eventName, m));
},

rezoneStart: function (eventName, msgs) {
events.emit('rezoneStart');

events.emit('destroyAllObjects');
events.emit('resetRenderer');
events.emit('resetPhysics');
events.emit('clearUis');

//Certain messages expect to be performed last (because the object they act on hasn't been created when they get queued)
r.sort(function (a, b) {
if (a.performLast)
return 1;
else if (b.performLast)
return -1;
return 0;
client.request({
threadModule: 'rezoneManager',
method: 'clientAck',
data: {}
});
},

r.forEach(function (o) {
events.emit(e, o);
getMap: function (eventName, msgs) {
events.emit('onGetMap', msgs[0]);

client.request({
threadModule: 'instancer',
method: 'clientAck',
data: {}
});
},

onGetObject: function (eventName, msgs) {
const prepend = msgs.filter(o => o.self);
msgs.spliceWhere(o => prepend.some(p => p === o));
msgs.unshift.apply(msgs, prepend);

this.processAction.default(eventName, msgs);
}
},

onEvent: function ({ event: eventName, data: eventData }) {
const handler = this.processAction[eventName] || this.processAction.default;

handler(eventName, [eventData]);
},

onEvents: function (response) {
for (let eventName in response) {
const eventMsgs = response[eventName];

const handler = this.processAction[eventName] || this.processAction.default;

handler(eventName, eventMsgs);
}
}
};


+ 2
- 2
src/client/ui/templates/death/death.js View File

@@ -20,14 +20,14 @@ define([
this.onEvent('onPermadeath', this.onPermadeath.bind(this));

this.find('.btn-logout').on('click', this.onLogout.bind(this));
this.find('.btn-respawn').on('click', this.onRespawn.bind(this));
this.find('.btn-respawn').on('click', this.performRespawn.bind(this));
},

onLogout: function () {
$('.uiMainMenu').data('ui').charSelect();
},

onRespawn: function () {
performRespawn: function () {
events.emit('onHideOverlay', this.el);
this.hide(true);



+ 2
- 2
src/client/ui/templates/events/events.js View File

@@ -26,7 +26,7 @@ define([
this.find('.btnCollapse').on('click', this.toggleButtons.bind(this));
}
this.onEvent('onRezone', this.onRezone.bind(this));
this.onEvent('clearUis', this.clear.bind(this));

this.onEvent('onObtainEvent', this.onObtainEvent.bind(this));
this.onEvent('onRemoveEvent', this.onRemoveEvent.bind(this));
@@ -37,7 +37,7 @@ define([
this.onToggleEventsVisibility(config.showEvents);
},

onRezone: function () {
clear: function () {
this.list = [];
this.el.find('.list').empty();
},


+ 4
- 2
src/client/ui/templates/mainMenu/mainMenu.js View File

@@ -58,8 +58,10 @@ define([
},

onCharSelect: function () {
renderer.clean();
objects.onRezone();
events.emit('destroyAllObjects');
events.emit('resetRenderer');
events.emit('resetPhysics');

renderer.buildTitleScreen();
sound.unload();



+ 2
- 2
src/client/ui/templates/quests/quests.js View File

@@ -25,7 +25,7 @@ define([
this.find('.btnCollapse').on('click', this.toggleButtons.bind(this));
}

this.onEvent('onRezone', this.onRezone.bind(this));
this.onEvent('clearUis', this.clear.bind(this));

this.onEvent('onObtainQuest', this.onObtainQuest.bind(this));
this.onEvent('onUpdateQuest', this.onUpdateQuest.bind(this));
@@ -35,7 +35,7 @@ define([
this.onToggleQuestsVisibility(config.showQuests);
},

onRezone: function () {
clear: function () {
this.quests = [];
this.el.find('.list').empty();
},


+ 1
- 5
src/client/ui/templates/talk/talk.js View File

@@ -18,11 +18,7 @@ define([

postRender: function () {
this.onEvent('onGetTalk', this.onGetTalk.bind(this));
this.onEvent('onRezone', this.onRezone.bind(this));
},

onRezone: function () {
this.hide();
this.onEvent('clearUis', this.hide.bind(this));
},

onGetTalk: function (dialogue) {


+ 3
- 1
src/server/.eslintrc View File

@@ -58,7 +58,9 @@
"leaderboard": false,
"clientConfig": false,
"random": false,
"consts": false
"consts": false,
"rezoneManager": false,
"eventManager": false
},

"rules": {


+ 0
- 8
src/server/clientComponents/gatherer.js View File

@@ -13,7 +13,6 @@ define([

init: function () {
this.obj.on('onKeyDown', this.onKeyDown.bind(this));
this.hookEvent('onRezone', this.onRezone.bind(this));
},

extend: function (msg) {
@@ -53,13 +52,6 @@ define([
}
},

onRezone: function () {
this.extend({
progress: 100,
action: 'Fishing'
});
},

onKeyDown: function (key) {
if (key !== 'g')
return;


+ 4
- 4
src/server/clientComponents/pather.js View File

@@ -27,9 +27,9 @@ define([
lastY: 0,

init: function () {
events.on('onRespawn', this.onDeath.bind(this));
events.on('onDeath', this.onDeath.bind(this));
events.on('onClearQueue', this.onDeath.bind(this));
events.on('teleportToPosition', this.resetPath.bind(this));
events.on('onDeath', this.resetPath.bind(this));
events.on('onClearQueue', this.resetPath.bind(this));

this.pathPos.x = round(this.obj.x);
this.pathPos.y = round(this.obj.y);
@@ -46,7 +46,7 @@ define([
this.path = [];
},

onDeath: function () {
resetPath: function () {
this.clearPath();
this.pathPos.x = round(this.obj.x);


+ 2
- 2
src/server/clientComponents/player.js View File

@@ -29,7 +29,7 @@ define([
obj.addComponent('serverActions');
obj.addComponent('pather');

this.hookEvent('onRespawn', this.onRespawn.bind(this));
this.hookEvent('teleportToPosition', this.teleportToPosition.bind(this));

events.emit('onGetPortrait', obj.portrait);
},
@@ -74,7 +74,7 @@ define([
}, instant);
},

onRespawn: function ({ x, y }) {
teleportToPosition: function ({ x, y }) {
this.positionCamera(x, y, true);
sound.update(x, y);
},


+ 1
- 1
src/server/components/player.js View File

@@ -235,7 +235,7 @@ module.exports = {

obj.instance.physics.addObject(obj, obj.x, obj.y);

obj.instance.syncer.queue('onRespawn', {
obj.instance.syncer.queue('teleportToPosition', {
x: obj.x,
y: obj.y
}, [obj.serverId]);


+ 32
- 19
src/server/components/portal/sendObjToZone.js View File

@@ -1,9 +1,9 @@
const sendObjToZone = async ({ obj, invokingObj, zoneName, toPos, toRelativePos }) => {
const { serverId, instance: { physics, syncer: globalSyncer } } = obj;

globalSyncer.flushForTarget(serverId);
const { serverId, instance: { syncer: globalSyncer, physics } } = obj;

if (obj.zoneName === zoneName) {
globalSyncer.flushForTarget(serverId);

physics.removeObject(obj, obj.x, obj.y);

if (toRelativePos) {
@@ -18,7 +18,7 @@ const sendObjToZone = async ({ obj, invokingObj, zoneName, toPos, toRelativePos

physics.addObject(obj, obj.x, obj.y);

globalSyncer.queue('onRespawn', {
globalSyncer.queue('teleportToPosition', {
x: obj.x,
y: obj.y
}, [obj.serverId]);
@@ -26,28 +26,41 @@ const sendObjToZone = async ({ obj, invokingObj, zoneName, toPos, toRelativePos
return;
}

obj.fireEvent('beforeRezone');

obj.destroyed = true;
//We set this before saving so that objects aren't saved ON portals
obj.zoneName = zoneName;
if (toPos) {
obj.x = toPos.x;
obj.y = toPos.y;
} else if (toRelativePos) {
obj.x = invokingObj.obj.x + toRelativePos.x;
obj.y = invokingObj.obj.y + toRelativePos.y;
}

//Destroy, flush events and notify other objects
globalSyncer.processDestroyedObject(obj);
await obj.auth.doSave();

//Test code, remove later
Object.entries(globalSyncer.buffer).forEach(([k, v]) => {
v.forEach(e => {
if (e.to.includes(serverId)) {
/* eslint-disable-next-line */
console.log('Found event', k, 'for rezoning object');
}
});
});

const simpleObj = obj.getSimple(true, false, true);

if (toPos) {
simpleObj.x = toPos.x;
simpleObj.y = toPos.y;
} else if (toRelativePos) {
simpleObj.x = invokingObj.obj.x + toRelativePos.x;
simpleObj.y = invokingObj.obj.y + toRelativePos.y;
}
rezoneManager.stageRezone(simpleObj, zoneName);

process.send({
method: 'rezone',
id: obj.serverId,
args: {
obj: simpleObj,
newZone: zoneName
method: 'events',
data: {
rezoneStart: [{
obj: { msg: {} },
to: [serverId]
}]
}
});
};


+ 3
- 0
src/server/components/social/rezone.js View File

@@ -3,6 +3,9 @@ const sendObjToZone = require('../portal/sendObjToZone');
module.exports = (cpnSocial, targetZone) => {
const { obj } = cpnSocial;

if (obj.zoneName === targetZone)
return;

sendObjToZone({
obj,
zoneName: targetZone


+ 2
- 2
src/server/events/phases/phaseGiveRewards.js View File

@@ -1,6 +1,6 @@
module.exports = {
init: function (event) {
const { config, rewards, eventManager } = event;
const { config, rewards, eventManager: eManager } = event;

const { name: eventName, rewardSenderName } = config;

@@ -26,7 +26,7 @@ module.exports = {
});

if ((config.events) && (config.events.afterGiveRewards))
config.events.afterGiveRewards(eventManager, config);
config.events.afterGiveRewards(eManager, config);

this.end = true;
}


+ 67
- 43
src/server/objects/objects.js View File

@@ -203,64 +203,80 @@ module.exports = {

return newO;
},
sendEvent: function (msg) {
let player = this.objects.find(p => p.id === msg.id);
if (!player)

sendEvent: function (msg, { name: sourceZone }) {
const { id, data } = msg;

const player = this.objects.find(p => p.id === id);
if (!player || player.zoneName !== sourceZone)
return;

player.socket.emit('event', {
event: msg.data.event,
data: msg.data.data
event: data.event,
data: data.data
});
},
sendEvents: function (msg) {
let players = {};
let objects = this.objects;

let data = msg.data;
sendEvents: function ({ data }, { name: sourceZone }) {
const { objects } = this;

//Store will contain all events to be sent to players
const store = {};

for (let e in data) {
let event = data[e];
let eLen = event.length;
const event = data[e];
const eLen = event.length;

for (let j = 0; j < eLen; j++) {
let eventEntry = event[j];

let obj = eventEntry.obj;

if (e !== 'serverModule') {
let to = eventEntry.to;
let toLen = to.length;
for (let i = 0; i < toLen; i++) {
let toId = to[i];

let player = players[toId];
if (!player) {
let findPlayer = objects.find(o => o.id === toId);
if (!findPlayer)
continue;
else {
player = (players[toId] = {
socket: findPlayer.socket,
events: {}
});
}
}

let eventList = player.events[e] || (player.events[e] = []);
eventList.push(obj);
const eventEntry = event[j];

const { obj: eventObj, to } = eventEntry;

if (e === 'serverModule') {
const { method, msg } = eventObj;

if (Array.isArray(msg))
global[eventObj.module][method](...msg);
else
global[eventObj.module][method](msg);

continue;
}

const toLen = to.length;
for (let i = 0; i < toLen; i++) {
const toId = to[i];

let storeEntry = store[toId];
if (!storeEntry) {
const playerObj = objects.find(o => o.id === toId);

if (!playerObj || playerObj.zoneName !== sourceZone)
continue;

store[toId] = {
obj: playerObj,
events: { [e]: [eventObj] }
};

continue;
}
} else if (obj.msg instanceof Array)
global[obj.module][obj.method](...obj.msg);
else
global[obj.module][obj.method](obj.msg);

if (!storeEntry.events[e])
storeEntry.events[e] = [];

storeEntry.events[e].push(eventObj);
}
}
}

for (let p in players) {
let player = players[p];
player.socket.emit('events', player.events);
for (let p in store) {
const { obj: { socket }, events } = store[p];

socket.emit('events', events);
}
},

updateObject: async function (msg) {
let player = this.objects.find(p => p.id === msg.serverId);
if (!player)
@@ -324,6 +340,14 @@ module.exports = {
if ((o.update) && (!o.destroyed))
o.update();

//When objects are sent to other zones, we destroy them immediately (thhrough sendObjToZone)
// In these cases, we DO need to remove it
if (o.forceDestroy) {
i--;
len--;
continue;
}

if (o.ttl) {
o.ttl--;
if (!o.ttl)


+ 3
- 1
src/server/security/routerConfig.js View File

@@ -24,7 +24,9 @@ const routerConfig = {
globalAllowed: {
clientConfig: ['getClientConfig'],
leaderboard: ['requestList'],
cons: ['unzone']
cons: ['unzone'],
rezoneManager: ['clientAck'],
instancer: ['clientAck']
},
allowTargetId: {
door: ['lock', 'unlock'],


+ 2
- 2
src/server/world/atlas.js View File

@@ -174,11 +174,11 @@ module.exports = {
},

event: function (thread, message) {
objects.sendEvent(message);
objects.sendEvent(message, thread);
},

events: function (thread, message) {
objects.sendEvents(message);
objects.sendEvents(message, thread);
},

object: function (thread, message) {


+ 20
- 8
src/server/world/instancer.js View File

@@ -13,6 +13,9 @@ let eventEmitter = require('../misc/events');
const mods = require('../misc/mods');
const transactions = require('../security/transactions');

//Own helpers
const { stageZoneIn, unstageZoneIn, clientAck } = require('./instancer/handshakes');

module.exports = {
instances: [],
zoneId: -1,
@@ -65,6 +68,9 @@ module.exports = {
[resourceSpawner, syncer, objects, questBuilder, events].forEach(i => i.init(fakeInstance));

this.tick();

this.clientAck = clientAck;
eventEmitter.on('removeObject', unstageZoneIn);
},

startRegen: function (respawnMap, respawnPos) {
@@ -211,15 +217,17 @@ module.exports = {

obj.spawn = map.spawn;

syncer.queue('onGetMap', map.clientMap, [obj.serverId]);
stageZoneIn(msg);

if (!msg.transfer)
objects.addObject(obj, this.onAddObject.bind(this));
else {
let o = objects.transferObject(obj);
questBuilder.obtain(o);
eventEmitter.emit('onAfterPlayerEnterZone', o);
}
process.send({
method: 'events',
data: {
getMap: [{
obj: map.clientMap,
to: [obj.serverId]
}]
}
});
},

onAddObject: function (obj) {
@@ -302,6 +310,10 @@ module.exports = {
return;
}

//We fire this event because even though an object might be destroyed already,
// mods and modules might have staged events/actions we need to clear
eventEmitter.emit('removeObject', { obj: msg.obj });

let obj = msg.obj;
obj = objects.find(o => o.serverId === obj.id);
if (!obj) {


+ 49
- 0
src/server/world/instancer/handshakes.js View File

@@ -0,0 +1,49 @@
//Local State
const stagedZoneIns = [];

//Methods

//Fired when an object is removed through a socket dc
// We do this because a client might DC during rezone handshake
const unstageZoneIn = msg => {
stagedZoneIns.spliceWhere(s => s.obj.serverId === msg.obj.id);
};

const stageZoneIn = msg => {
const { serverId } = msg.obj;

stagedZoneIns.spliceWhere(o => o.obj.serverId === serverId);

stagedZoneIns.push(msg);
};

const doZoneIn = function (staged) {
const { onAddObject, instances: [ { objects, questBuilder, eventEmitter } ] } = instancer;

const { transfer, obj } = staged;

if (!transfer)
objects.addObject(obj, onAddObject.bind(instancer));
else {
let o = objects.transferObject(obj);
questBuilder.obtain(o);
eventEmitter.emit('onAfterPlayerEnterZone', o);
}
};

const clientAck = msg => {
const staged = stagedZoneIns.find(s => s.obj.serverId === msg.sourceId);
if (!staged)
return;

stagedZoneIns.spliceWhere(s => s === staged);

doZoneIn(staged);
};

//Exports
module.exports = {
unstageZoneIn,
stageZoneIn,
clientAck
};

+ 55
- 0
src/server/world/rezoneManager.js View File

@@ -0,0 +1,55 @@
//Imports
const eventEmitter = require('../misc/events');

//Local State
const stagedRezones = [];

//Methods

//Fired when an object is removed through a socket dc
// We do this because a client might DC during rezone handshake
const unstageRezone = msg => {
stagedRezones.spliceWhere(s => s.simplifiedObj.serverId === msg.obj.id);
};

const stageRezone = (simplifiedObj, targetZone) => {
const { serverId } = simplifiedObj;

stagedRezones.spliceWhere(o => o.simplifiedObj.serverId === serverId);

stagedRezones.push({ simplifiedObj, targetZone });
};

const doRezone = stagedRezone => {
const { simplifiedObj, targetZone } = stagedRezone;

process.send({
method: 'rezone',
id: simplifiedObj.serverId,
args: {
obj: simplifiedObj,
newZone: targetZone
}
});
};

const clientAck = msg => {
const staged = stagedRezones.find(s => s.simplifiedObj.serverId === msg.sourceId);
if (!staged)
return;

stagedRezones.spliceWhere(s => s === staged);

doRezone(staged);
};

const init = () => {
eventEmitter.on('removeObject', unstageRezone);
};

//Exports
module.exports = {
init,
stageRezone,
clientAck
};

+ 0
- 1
src/server/world/spawners.js View File

@@ -60,7 +60,6 @@ module.exports = {

this.syncer.queue('onGetObject', {
id: obj.id,
performLast: true,
components: [spawnAnimation]
}, -1);
}


+ 29
- 0
src/server/world/syncer.js View File

@@ -180,6 +180,35 @@ module.exports = {
}
},

processDestroyedObject: function (obj) {
const { objects, queue } = this;
const { id, serverId } = obj;

obj.destroyed = true;

//We mark forceDestroy to tell objects that we're destroying an object outside of the
// syncer's update method
obj.forceDestroy = true;

const msg = {
id: id,
destroyed: true
};

objects.removeObject(obj);

this.flushForTarget(serverId);

const fnQueueMsg = queue.bind(this, 'onGetObject');

//Find any players that have seen this obj
objects
.filter(o => !o.destroyed && o?.player?.hasSeen(id))
.forEach(o => {
fnQueueMsg(msg);
});
},

send: function () {
if (!this.dirty)
return;


+ 3
- 0
src/server/world/worker.js View File

@@ -5,6 +5,7 @@ global.consts = require('../config/consts');
global.instancer = require('./instancer');
global.eventManager = require('../events/events');
global.clientConfig = require('../config/clientConfig');
global.rezoneManager = require('./rezoneManager');

const components = require('../components/components');
const mods = require('../misc/mods');
@@ -33,6 +34,8 @@ let onCpnsReady = async function () {
recipes.init();
itemEffects.init();
profanities.init();
rezoneManager.init();

await clientConfig.init();

process.send({


Loading…
Cancel
Save