From db562ce6a05bdcb04794117eb837ff3e14d433ed Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Wed, 6 Jul 2022 15:07:10 +0200 Subject: [PATCH] Provide reason for player leaving Expose the reason for why a player is leaving a server in playerEvent. --- packages/lib/link/messages.js | 2 ++ packages/lib/plugin.js | 6 ++++++ packages/slave/modules/clusterio/impl.lua | 11 ++++++++++- packages/slave/src/Instance.js | 18 ++++++++++++++---- test/slave/Instance.js | 10 +++++----- 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/packages/lib/link/messages.js b/packages/lib/link/messages.js index dd187266..01f75da0 100644 --- a/packages/lib/link/messages.js +++ b/packages/lib/link/messages.js @@ -1284,10 +1284,12 @@ messages.playerEvent = new Event({ type: "player_event", links: ["instance-slave", "slave-master"], forwardTo: "master", + eventRequired: ["instance_id", "type", "name"], eventProperties: { "instance_id": { type: "integer" }, "type": { type: "string", enum: ["join", "leave"] }, "name": { type: "string" }, + "reason": { type: "string" }, }, }); diff --git a/packages/lib/plugin.js b/packages/lib/plugin.js index b9810254..23499e4b 100644 --- a/packages/lib/plugin.js +++ b/packages/lib/plugin.js @@ -208,6 +208,9 @@ class BaseInstancePlugin { * @param {Object} event - Information about the event. * @param {string} event.type - Either "join" or "leave". * @param {string} event.name - Name of the player that joined/left. + * @param {string=} event.reason - + * Only present for type "leave". Reason for player leaving the + * game, one of the possible reasons in defines.disconnect_reason. */ async onPlayerEvent(event) { } @@ -500,6 +503,9 @@ class BaseMasterPlugin { * @param {Object} event - Information about the event. * @param {string} event.type - Either "join" or "leave". * @param {string} event.name - Name of the player that joined/left. + * @param {string=} event.reason - + * Only present for type "leave". Reason for player leaving the + * game, one of the possible reasons in defines.disconnect_reason. */ async onPlayerEvent(instance, event) { } diff --git a/packages/slave/modules/clusterio/impl.lua b/packages/slave/modules/clusterio/impl.lua index cdb1d68e..acce50ee 100644 --- a/packages/slave/modules/clusterio/impl.lua +++ b/packages/slave/modules/clusterio/impl.lua @@ -28,9 +28,18 @@ impl.events[defines.events.on_player_joined_game] = function(event) api.send_json("player_event", { type = "join", name = player.name }) end +local disconnect_reason_name = {} +for name, i in pairs(defines.disconnect_reason) do + disconnect_reason_name[i] = name +end + impl.events[defines.events.on_player_left_game] = function(event) local player = game.players[event.player_index] - api.send_json("player_event", { type = "leave", name = player.name }) + api.send_json("player_event", { + type = "leave", + name = player.name, + reason = disconnect_reason_name[event.reason], + }) end -- Internal API diff --git a/packages/slave/src/Instance.js b/packages/slave/src/Instance.js index 062a7017..9207cad9 100644 --- a/packages/slave/src/Instance.js +++ b/packages/slave/src/Instance.js @@ -250,7 +250,7 @@ class Instance extends libLink.Link { if (event.type === "join") { this._recordPlayerJoin(event.name); } else if (event.type === "leave") { - this._recordPlayerLeave(event.name); + this._recordPlayerLeave(event.name, event.reason); } }); @@ -264,6 +264,9 @@ class Instance extends libLink.Link { * Unix timestamp in ms the player was last seen leaving this * instance. Not present if player has yet to leave after first * time joining. + * @property {string=} lastLeaveReason - + * Reason the player was last seen leaving with. Not present if + * player has yet to leave after first time joining. * @property {number} joinCount - * Count of the number of times this player has been seen * joining this server. @@ -297,7 +300,12 @@ class Instance extends libLink.Link { if (parsed.action === "JOIN") { this._recordPlayerJoin(name); } else if (["LEAVE", "KICK", "BAN"].includes(parsed.action)) { - this._recordPlayerLeave(name); + let reason = { + "LEAVE": "quit", + "KICK": "kicked", + "BAN": "banned", + }[parsed.action]; + this._recordPlayerLeave(name, reason); } }); @@ -322,7 +330,7 @@ class Instance extends libLink.Link { this.playersOnline.forEach(player => joined.delete(player)); for (let player of left) { - this._recordPlayerLeave(player); + this._recordPlayerLeave(player, "quit"); } // Missing join messages is not supposed to happen. @@ -358,13 +366,14 @@ class Instance extends libLink.Link { libPlugin.invokeHook(this.plugins, "onPlayerEvent", event); } - _recordPlayerLeave(name) { + _recordPlayerLeave(name, reason) { if (!this.playersOnline.delete(name)) { return; } let stats = this.playerStats.get(name); stats.lastLeaveAt = Date.now(); + stats.lastLeaveReason = reason; stats.onlineTimeMs += stats.lastLeaveAt - stats.lastJoinAt; this._hadPlayersOnline = true; @@ -372,6 +381,7 @@ class Instance extends libLink.Link { instance_id: this.id, type: "leave", name, + reason, }; libLink.messages.playerEvent.send(this, event); libPlugin.invokeHook(this.plugins, "onPlayerEvent", event); diff --git a/test/slave/Instance.js b/test/slave/Instance.js index 0008489f..142e1cd0 100644 --- a/test/slave/Instance.js +++ b/test/slave/Instance.js @@ -89,21 +89,21 @@ describe("class Instance", function() { it("should send player_event", function() { instance._recordPlayerJoin("player"); - instance._recordPlayerLeave("player"); + instance._recordPlayerLeave("player", "quit"); assert.deepEqual( connector.sentMessages[1], { seq: 2, type: "player_event_event", - data: { type: "leave", instance_id: instance.id, name: "player" }, + data: { type: "leave", instance_id: instance.id, name: "player", reason: "quit" }, }, ); }); it("should be idempotent", function() { instance._recordPlayerJoin("player"); - instance._recordPlayerLeave("player"); - instance._recordPlayerLeave("player"); + instance._recordPlayerLeave("player", "quit"); + instance._recordPlayerLeave("player", "quit"); assert(!instance.playersOnline.has("player"), "player was not removed"); assert.equal(connector.sentMessages.length, 2); }); @@ -148,7 +148,7 @@ describe("class Instance", function() { { seq: 2, type: "player_event_event", - data: { type: "leave", instance_id: instance.id, name: "player" }, + data: { type: "leave", instance_id: instance.id, name: "player", reason: "quit" }, }, ); });