diff --git a/src/server/components/aggro.js b/src/server/components/aggro.js index 23a05e59..95e743aa 100644 --- a/src/server/components/aggro.js +++ b/src/server/components/aggro.js @@ -414,7 +414,7 @@ module.exports = { setAllAmounts: function (amount) { this.list.forEach(l => { - l.amount = amount; + l.threat = amount; }); } }; diff --git a/src/server/security/connections.js b/src/server/security/connections.js index 94771b05..b1d3bad6 100644 --- a/src/server/security/connections.js +++ b/src/server/security/connections.js @@ -25,7 +25,7 @@ module.exports = { this.players.push(p); }, - onDisconnect: function (socket) { + onDisconnect: async function (socket) { let player = this.players.find(p => p.socket.id === socket.id); if (!player) diff --git a/src/server/world/atlas.js b/src/server/world/atlas.js index 113821a5..65290811 100644 --- a/src/server/world/atlas.js +++ b/src/server/world/atlas.js @@ -2,14 +2,13 @@ const objects = require('../objects/objects'); const events = require('../misc/events'); const { - getThread, killThread, sendMessageToThread, getThreadFromId, returnWhenThreadsIdle + getThread, killThread, sendMessageToThread, getThreadFromId, returnWhenThreadsIdle, canThreadBeClosed } = require('./threadManager'); +const { registerCallback, removeCallback } = require('./atlas/registerCallback'); //Exports module.exports = { nextId: 0, - lastCallbackId: 0, - callbacks: [], addObject: async function (obj, keepPos, transfer) { const serverObj = objects.objects.find(o => o.id === obj.id); @@ -80,7 +79,7 @@ module.exports = { callback(); }, - removeObject: function (obj, skipLocal, callback) { + removeObject: async function (obj, skipLocal, callback) { if (!skipLocal) objects.removeObject(obj); @@ -88,7 +87,7 @@ module.exports = { if (!thread) return; - if (thread.instanced) { + if (thread.instanced && await canThreadBeClosed(thread, this.registerCallback.bind(this))) { this.removeObjectFromInstancedZone(thread, obj, callback); return; @@ -147,15 +146,11 @@ module.exports = { }, registerCallback: function (callback) { - this.callbacks.push({ - id: ++this.lastCallbackId, - callback: callback - }); - - return this.lastCallbackId; + return registerCallback(callback); }, + resolveCallback: function (msg) { - let callback = this.callbacks.spliceFirstWhere(c => c.id === msg.msg.id); + const callback = removeCallback(msg.msg.id); if (!callback) return; diff --git a/src/server/world/atlas/registerCallback.js b/src/server/world/atlas/registerCallback.js new file mode 100644 index 00000000..34e7b2fd --- /dev/null +++ b/src/server/world/atlas/registerCallback.js @@ -0,0 +1,22 @@ +let lastCallbackId = 0; +const callbacks = []; + +const registerCallback = callback => { + callbacks.push({ + id: ++lastCallbackId, + callback + }); + + return lastCallbackId; +}; + +const removeCallback = callbackId => { + const callback = callbacks.spliceFirstWhere(c => c.id === callbackId); + + return callback; +}; + +module.exports = { + registerCallback, + removeCallback +}; diff --git a/src/server/world/instancer.js b/src/server/world/instancer.js index 8a505556..e6361560 100644 --- a/src/server/world/instancer.js +++ b/src/server/world/instancer.js @@ -385,6 +385,18 @@ module.exports = { id: callbackId } }); - } + }, + getPlayerCount: function ({ callbackId }) { + process.send({ + module: 'atlas', + method: 'resolveCallback', + msg: { + id: callbackId, + result: { + playerCount: objects.objects.filter(o => o.player !== undefined).length + } + } + }); + } }; diff --git a/src/server/world/threadManager.js b/src/server/world/threadManager.js index 95bdb71f..bcb05b48 100644 --- a/src/server/world/threadManager.js +++ b/src/server/world/threadManager.js @@ -5,6 +5,7 @@ const childProcess = require('child_process'); const objects = require('../objects/objects'); const connections = require('../security/connections'); const { mapList } = require('./mapManager'); +const { registerCallback } = require('./atlas/registerCallback'); //Internals const threads = []; @@ -19,6 +20,21 @@ const getThreadFromId = threadId => { return threads.find(t => t.id === threadId); }; +const canThreadBeClosed = async thread => { + const { playerCount } = await new Promise(res => { + const cb = registerCallback(res); + + thread.worker.send({ + method: 'getPlayerCount', + args: { + callbackId: cb + } + }); + }); + + return playerCount === 0; +}; + const messageHandlers = { onReady: function (thread) { thread.worker.send({ @@ -78,7 +94,7 @@ const messageHandlers = { rezone: async function (thread, message) { const { args: { obj, newZone, keepPos = true } } = message; - if (thread.instanced) { + if (thread.instanced && await canThreadBeClosed(thread)) { thread.worker.kill(); threads.spliceWhere(t => t === thread); } @@ -242,5 +258,6 @@ module.exports = { spawnMapThreads, messageAllThreads, sendMessageToThread, - returnWhenThreadsIdle + returnWhenThreadsIdle, + canThreadBeClosed };