From 3a68968e9a149e5ae226fb5201d4a587afacc5d6 Mon Sep 17 00:00:00 2001 From: Tabby Dev <88893827+Tabby-Labs@users.noreply.github.com> Date: Tue, 20 May 2025 09:45:16 +0800 Subject: [PATCH 01/23] fix(esx_multicharacter/server/modules/functions): fix failed to reconnect after client crashed --- [core]/esx_multicharacter/server/modules/functions.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/[core]/esx_multicharacter/server/modules/functions.lua b/[core]/esx_multicharacter/server/modules/functions.lua index 8792cec1..6c816571 100644 --- a/[core]/esx_multicharacter/server/modules/functions.lua +++ b/[core]/esx_multicharacter/server/modules/functions.lua @@ -27,7 +27,7 @@ function Server:OnConnecting(source, deferrals) deferrals.defer() Wait(0) -- Required local identifier = self:GetIdentifier(source) - + -- luacheck: ignore if not SetEntityOrphanMode then return deferrals.done(("[ESX] ESX Requires a minimum Artifact version of 10188, Please update your server.")) @@ -47,7 +47,7 @@ function Server:OnConnecting(source, deferrals) if identifier then if not ESX.GetConfig().EnableDebug then - if ESX.Players[identifier] then + if not source and ESX.Players[identifier] then deferrals.done(("[ESX Multicharacter] A player is already connected to the server with this identifier.\nYour identifier: %s:%s"):format(Server.identifierType, identifier)) else deferrals.done() From 7b84a02ef2862b401695ff69858d9cc1ce43ad32 Mon Sep 17 00:00:00 2001 From: Tabby Dev <88893827+Tabby-Labs@users.noreply.github.com> Date: Tue, 20 May 2025 10:07:21 +0800 Subject: [PATCH 02/23] fix(es_extended/server/main): fix failed to reconnect after client crashed --- [core]/es_extended/server/main.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/[core]/es_extended/server/main.lua b/[core]/es_extended/server/main.lua index fe0821a0..993e99ec 100644 --- a/[core]/es_extended/server/main.lua +++ b/[core]/es_extended/server/main.lua @@ -50,7 +50,7 @@ local function onPlayerJoined(playerId) return DropPlayer(playerId, "there was an error loading your character!\nError code: identifier-missing-ingame\n\nThe cause of this error is not known, your identifier could not be found. Please come back later or report this problem to the server administration team.") end - if ESX.GetPlayerFromIdentifier(identifier) then + if not playerId and ESX.GetPlayerFromIdentifier(identifier) then DropPlayer( playerId, ("there was an error loading your character!\nError code: identifier-active-ingame\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same Rockstar account.\n\nYour Rockstar identifier: %s"):format( @@ -116,7 +116,7 @@ if not Config.Multichar then end if identifier then - if ESX.GetPlayerFromIdentifier(identifier) then + if not playerId and ESX.GetPlayerFromIdentifier(identifier) then return deferrals.done( ("[ESX] There was an error loading your character!\nError code: identifier-active\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same account.\n\nYour identifier: %s"):format(identifier) ) From 3603962413ad75eafaf1ac44cac6d92811fc2f53 Mon Sep 17 00:00:00 2001 From: Tabby Dev <88893827+Tabby-Labs@users.noreply.github.com> Date: Tue, 20 May 2025 14:13:13 +0800 Subject: [PATCH 03/23] fix(es_extended/server/main): remove old player from memory (non multichar) --- [core]/es_extended/server/main.lua | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/[core]/es_extended/server/main.lua b/[core]/es_extended/server/main.lua index 993e99ec..b54450bb 100644 --- a/[core]/es_extended/server/main.lua +++ b/[core]/es_extended/server/main.lua @@ -50,7 +50,7 @@ local function onPlayerJoined(playerId) return DropPlayer(playerId, "there was an error loading your character!\nError code: identifier-missing-ingame\n\nThe cause of this error is not known, your identifier could not be found. Please come back later or report this problem to the server administration team.") end - if not playerId and ESX.GetPlayerFromIdentifier(identifier) then + if ESX.GetPlayerFromIdentifier(identifier) then DropPlayer( playerId, ("there was an error loading your character!\nError code: identifier-active-ingame\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same Rockstar account.\n\nYour Rockstar identifier: %s"):format( @@ -115,17 +115,27 @@ if not Config.Multichar then return deferrals.done("[ESX] OxMySQL Was Unable To Connect to your database. Please make sure it is turned on and correctly configured in your server.cfg") end - if identifier then - if not playerId and ESX.GetPlayerFromIdentifier(identifier) then + if not identifier then + return deferrals.done("[ESX] There was an error loading your character!\nError code: identifier-missing\n\nThe cause of this error is not known, your identifier could not be found. Please come back later or report this problem to the server administration team.") + end + + local xIdentifier = ESX.GetPlayerFromIdentifier(identifier) + + if not playerId and xIdentifier then + local xId = xIdentifier.playerId + + if ESX.Players[xId] then + ESX.Players[xId] = nil + Core.playersByIdentifier[identifier] = nil + print(("[ESX] Cleaning old ESX.Players entry for %s (ped invalid)"):format(identifier)) + else return deferrals.done( ("[ESX] There was an error loading your character!\nError code: identifier-active\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same account.\n\nYour identifier: %s"):format(identifier) ) - else - return deferrals.done() end - else - return deferrals.done("[ESX] There was an error loading your character!\nError code: identifier-missing\n\nThe cause of this error is not known, your identifier could not be found. Please come back later or report this problem to the server administration team.") end + + return deferrals.done() end) end From 86e9735b81eb4e12936e8d2aec7dd86fe032407b Mon Sep 17 00:00:00 2001 From: Tabby Dev <88893827+Tabby-Labs@users.noreply.github.com> Date: Tue, 20 May 2025 16:01:16 +0800 Subject: [PATCH 04/23] fix(esx_multicharacter/server/modules/functions): remove old player from memory after crashing --- .../esx_multicharacter/server/modules/functions.lua | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/[core]/esx_multicharacter/server/modules/functions.lua b/[core]/esx_multicharacter/server/modules/functions.lua index 6c816571..ccf113d3 100644 --- a/[core]/esx_multicharacter/server/modules/functions.lua +++ b/[core]/esx_multicharacter/server/modules/functions.lua @@ -47,8 +47,16 @@ function Server:OnConnecting(source, deferrals) if identifier then if not ESX.GetConfig().EnableDebug then - if not source and ESX.Players[identifier] then - deferrals.done(("[ESX Multicharacter] A player is already connected to the server with this identifier.\nYour identifier: %s:%s"):format(Server.identifierType, identifier)) + if ESX.Players[identifier] then + local identifierExist = ESX.GetPlayerFromIdentifier(identifier) + + if not identifierExist then -- no player found + ESX.Players[identifier] = nil + print(('[ESX Multicharacter] no player found for identifier (%s), removing from ESX.Players'):format(identifier)) + deferrals.done() + else -- player found + deferrals.done(("[ESX Multicharacter] A player is already connected to the server with this identifier.\nYour identifier: %s:%s"):format(Server.identifierType, identifier)) + end else deferrals.done() end From 0ece059c1934b377e050cd760ef9437b8467bd9f Mon Sep 17 00:00:00 2001 From: Tabby Dev <88893827+Tabby-Labs@users.noreply.github.com> Date: Wed, 21 May 2025 13:48:26 +0800 Subject: [PATCH 05/23] fix(es_extended/server/main): add fallback check if player is exist --- [core]/es_extended/server/main.lua | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/[core]/es_extended/server/main.lua b/[core]/es_extended/server/main.lua index b54450bb..a276dafc 100644 --- a/[core]/es_extended/server/main.lua +++ b/[core]/es_extended/server/main.lua @@ -119,19 +119,23 @@ if not Config.Multichar then return deferrals.done("[ESX] There was an error loading your character!\nError code: identifier-missing\n\nThe cause of this error is not known, your identifier could not be found. Please come back later or report this problem to the server administration team.") end - local xIdentifier = ESX.GetPlayerFromIdentifier(identifier) + local xPlayer = ESX.GetPlayerFromIdentifier(identifier) - if not playerId and xIdentifier then - local xId = xIdentifier.playerId + if xPlayer then + local xPlayerId = xPlayer.playerId - if ESX.Players[xId] then - ESX.Players[xId] = nil - Core.playersByIdentifier[identifier] = nil - print(("[ESX] Cleaning old ESX.Players entry for %s (ped invalid)"):format(identifier)) - else - return deferrals.done( - ("[ESX] There was an error loading your character!\nError code: identifier-active\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same account.\n\nYour identifier: %s"):format(identifier) - ) + if ESX.Players[xPlayerId] then + local xPlayerExist = DoesPlayerExist(xPlayerId --[[@as string]]) + + if xPlayerExist ~= 0 then + ESX.Players[xPlayerId] = nil + Core.playersByIdentifier[identifier] = nil + deferrals.update(("[ESX] Cleaning old Player entry for [%s] (player invalid)"):format(identifier)) + else + return deferrals.done( + ("[ESX] There was an error loading your character!\nError code: identifier-active\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same account.\n\nYour identifier: %s"):format(identifier) + ) + end end end From 4bd80ca3e649590068a3e2285449ce15ad50afd4 Mon Sep 17 00:00:00 2001 From: Tabby Dev <88893827+Tabby-Labs@users.noreply.github.com> Date: Thu, 22 May 2025 19:10:31 +0800 Subject: [PATCH 06/23] feat(es_extended/server/main): add new handler 'esx:playerCrashed' for unloading players stale --- [core]/es_extended/server/main.lua | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/[core]/es_extended/server/main.lua b/[core]/es_extended/server/main.lua index 993e99ec..a4d5a07d 100644 --- a/[core]/es_extended/server/main.lua +++ b/[core]/es_extended/server/main.lua @@ -368,6 +368,25 @@ AddEventHandler("esx:playerLogout", function(playerId, cb) TriggerClientEvent("esx:onPlayerLogout", playerId) end) +AddEventHandler('esx:playerCrashed', function(identifier, cb) + local xPlayer = ESX.GetPlayerFromIdentifier(identifier) + + if xPlayer then + local playerId = xPlayer.playerId + local isExist = DoesPlayerExist(playerId --[[@as string]]) + + if playerId and isExist ~= 0 then + TriggerEvent('esx:playerDropped', playerId) + GlobalState["playerCount"] = GlobalState["playerCount"] - 1 + Core.playersByIdentifier[identifier] = nil + ESX.Players[playerId] = nil + if cb then + cb() + end + end + end +end) + if not Config.CustomInventory then RegisterNetEvent("esx:updateWeaponAmmo", function(weaponName, ammoCount) local xPlayer = ESX.GetPlayerFromId(source) From af52ca38519075ce64a83fafd2d9485734c8dc02 Mon Sep 17 00:00:00 2001 From: Tabby Dev <88893827+Tabby-Labs@users.noreply.github.com> Date: Thu, 22 May 2025 19:13:42 +0800 Subject: [PATCH 07/23] refactor(es_extended/server/main): use 'esx:playerCrashed' for consistency --- [core]/es_extended/server/main.lua | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/[core]/es_extended/server/main.lua b/[core]/es_extended/server/main.lua index a4d5a07d..95626930 100644 --- a/[core]/es_extended/server/main.lua +++ b/[core]/es_extended/server/main.lua @@ -115,17 +115,15 @@ if not Config.Multichar then return deferrals.done("[ESX] OxMySQL Was Unable To Connect to your database. Please make sure it is turned on and correctly configured in your server.cfg") end - if identifier then - if not playerId and ESX.GetPlayerFromIdentifier(identifier) then - return deferrals.done( - ("[ESX] There was an error loading your character!\nError code: identifier-active\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same account.\n\nYour identifier: %s"):format(identifier) - ) - else - return deferrals.done() - end - else + if not identifier then return deferrals.done("[ESX] There was an error loading your character!\nError code: identifier-missing\n\nThe cause of this error is not known, your identifier could not be found. Please come back later or report this problem to the server administration team.") end + + TriggerEvent('esx:playerCrashed', identifier, function() + deferrals.update(("[ESX] Cleaning old Player entry for [%s] (player invalid)"):format(identifier)) + end) + + return deferrals.done() end) end From 2cb6531f823bb01f9b97c59c8b22e84409f9c1bb Mon Sep 17 00:00:00 2001 From: Tabby Dev <88893827+Tabby-Labs@users.noreply.github.com> Date: Thu, 22 May 2025 19:17:24 +0800 Subject: [PATCH 08/23] refactor(esx_multicharacter/server/modules/functions): use 'esx:playerCrashed' for consistency --- .../server/modules/functions.lua | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/[core]/esx_multicharacter/server/modules/functions.lua b/[core]/esx_multicharacter/server/modules/functions.lua index 6c816571..b46dd43a 100644 --- a/[core]/esx_multicharacter/server/modules/functions.lua +++ b/[core]/esx_multicharacter/server/modules/functions.lua @@ -45,19 +45,17 @@ function Server:OnConnecting(source, deferrals) deferrals.done("[ESX Multicharacter] OxMySQL Was Unable To Connect to your database. Please make sure it is turned on and correctly configured in your server.cfg") end - if identifier then - if not ESX.GetConfig().EnableDebug then - if not source and ESX.Players[identifier] then - deferrals.done(("[ESX Multicharacter] A player is already connected to the server with this identifier.\nYour identifier: %s:%s"):format(Server.identifierType, identifier)) - else - deferrals.done() - end - else - deferrals.done() - end - else - deferrals.done(("[ESX Multicharacter] Unable to retrieve player identifier.\nIdentifier type: %s"):format(Server.identifierType)) - end + if not identifier then return deferrals.done(("[ESX Multicharacter] Unable to retrieve player identifier.\nIdentifier type: %s"):format(Server.identifierType)) end + + if ESX.GetConfig().EnableDebug or not ESX.Players[identifier] then deferrals.done() end + + TriggerEvent('esx:playerCrashed', identifier, function() + ESX.Players[identifier] = nil + deferrals.update(('[ESX] Cleaning old Player entry for [%s] (player invalid)'):format(identifier)) + end) + + deferrals.done() -- proceed end + Server:ResetPlayers() From 7d3fd2767600de15c3a6b73ddb31020c4f20d83d Mon Sep 17 00:00:00 2001 From: Tabby Dev <88893827+Tabby-Labs@users.noreply.github.com> Date: Thu, 22 May 2025 19:22:52 +0800 Subject: [PATCH 09/23] refactor(es_extended/server/main): use 'esx:playerCrashed' for consistency --- [core]/es_extended/server/main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/[core]/es_extended/server/main.lua b/[core]/es_extended/server/main.lua index 95626930..e593608c 100644 --- a/[core]/es_extended/server/main.lua +++ b/[core]/es_extended/server/main.lua @@ -50,7 +50,7 @@ local function onPlayerJoined(playerId) return DropPlayer(playerId, "there was an error loading your character!\nError code: identifier-missing-ingame\n\nThe cause of this error is not known, your identifier could not be found. Please come back later or report this problem to the server administration team.") end - if not playerId and ESX.GetPlayerFromIdentifier(identifier) then + if ESX.GetPlayerFromIdentifier(identifier) then DropPlayer( playerId, ("there was an error loading your character!\nError code: identifier-active-ingame\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same Rockstar account.\n\nYour Rockstar identifier: %s"):format( From 20e36fa15a20da0b5f273d4836bcb18447b7970b Mon Sep 17 00:00:00 2001 From: Tabby Dev <88893827+Tabby-Labs@users.noreply.github.com> Date: Fri, 30 May 2025 21:20:04 +0800 Subject: [PATCH 10/23] undo(es_extended/server/main.lua): revert 'playerConnecting' stale data removing logic --- [core]/es_extended/server/main.lua | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/[core]/es_extended/server/main.lua b/[core]/es_extended/server/main.lua index e593608c..d0bbfed5 100644 --- a/[core]/es_extended/server/main.lua +++ b/[core]/es_extended/server/main.lua @@ -119,9 +119,24 @@ if not Config.Multichar then return deferrals.done("[ESX] There was an error loading your character!\nError code: identifier-missing\n\nThe cause of this error is not known, your identifier could not be found. Please come back later or report this problem to the server administration team.") end - TriggerEvent('esx:playerCrashed', identifier, function() - deferrals.update(("[ESX] Cleaning old Player entry for [%s] (player invalid)"):format(identifier)) - end) + local xPlayer = ESX.GetPlayerFromIdentifier(identifier) + + if xPlayer and ESX.Players[xPlayer.playerId] then + local xPlayerId = xPlayer.playerId + local isExist = DoesPlayerExist(xPlayerId --[[@as string]]) + + if isExist ~= 0 then + deferrals.update(("[ESX] Cleaning old Player entry for [%s] (player invalid)"):format(identifier)) + TriggerEvent('esx:playerDropped', xPlayerId) + ESX.Players[xPlayerId] = nil + Core.playersByIdentifier[identifier] = nil + GlobalState['playerCount'] = GlobalState['playerCount'] - 1 + else + return deferrals.done( + ("[ESX] There was an error loading your character!\nError code: identifier-active\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same account.\n\nYour identifier: %s"):format(identifier) + ) + end + end return deferrals.done() end) From 5e6fbd1661e7f092d658018c199e7e1bd2adbf5c Mon Sep 17 00:00:00 2001 From: Kenshin13 <63159154+Kenshiin13@users.noreply.github.com> Date: Sat, 14 Jun 2025 20:39:44 +0200 Subject: [PATCH 11/23] fix(es_extended/server/main): player doesnt have to be in both tables. --- [core]/es_extended/server/main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/[core]/es_extended/server/main.lua b/[core]/es_extended/server/main.lua index d0bbfed5..c24b03f2 100644 --- a/[core]/es_extended/server/main.lua +++ b/[core]/es_extended/server/main.lua @@ -121,7 +121,7 @@ if not Config.Multichar then local xPlayer = ESX.GetPlayerFromIdentifier(identifier) - if xPlayer and ESX.Players[xPlayer.playerId] then + if xPlayer then local xPlayerId = xPlayer.playerId local isExist = DoesPlayerExist(xPlayerId --[[@as string]]) From 85881a4fde0e2244dba0dc1d622b9f4faee7e809 Mon Sep 17 00:00:00 2001 From: Kenshin13 <63159154+Kenshiin13@users.noreply.github.com> Date: Sat, 14 Jun 2025 20:40:27 +0200 Subject: [PATCH 12/23] refactor(es_extended/server/main): early return --- [core]/es_extended/server/main.lua | 33 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/[core]/es_extended/server/main.lua b/[core]/es_extended/server/main.lua index c24b03f2..2f6be680 100644 --- a/[core]/es_extended/server/main.lua +++ b/[core]/es_extended/server/main.lua @@ -121,24 +121,25 @@ if not Config.Multichar then local xPlayer = ESX.GetPlayerFromIdentifier(identifier) - if xPlayer then - local xPlayerId = xPlayer.playerId - local isExist = DoesPlayerExist(xPlayerId --[[@as string]]) - - if isExist ~= 0 then - deferrals.update(("[ESX] Cleaning old Player entry for [%s] (player invalid)"):format(identifier)) - TriggerEvent('esx:playerDropped', xPlayerId) - ESX.Players[xPlayerId] = nil - Core.playersByIdentifier[identifier] = nil - GlobalState['playerCount'] = GlobalState['playerCount'] - 1 - else - return deferrals.done( - ("[ESX] There was an error loading your character!\nError code: identifier-active\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same account.\n\nYour identifier: %s"):format(identifier) - ) - end + if not xPlayer then + return deferrals.done() + end + + local xPlayerId = xPlayer.playerId + local isExist = DoesPlayerExist(xPlayerId --[[@as string]]) + + if isExist ~= 0 then + deferrals.update(("[ESX] Cleaning old Player entry for [%s] (player invalid)"):format(identifier)) + TriggerEvent('esx:playerDropped', xPlayerId) + ESX.Players[xPlayerId] = nil + Core.playersByIdentifier[identifier] = nil + GlobalState['playerCount'] = GlobalState['playerCount'] - 1 + else + return deferrals.done( + ("[ESX] There was an error loading your character!\nError code: identifier-active\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same account.\n\nYour identifier: %s"):format(identifier) + ) end - return deferrals.done() end) end From 0c096c634f23fa18e93e01ce925ca863517173ed Mon Sep 17 00:00:00 2001 From: Kenshin13 <63159154+Kenshiin13@users.noreply.github.com> Date: Sat, 14 Jun 2025 20:47:08 +0200 Subject: [PATCH 13/23] refactor(es_extended/server/main): early return & more readable --- [core]/es_extended/server/main.lua | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/[core]/es_extended/server/main.lua b/[core]/es_extended/server/main.lua index 2f6be680..f81c13e7 100644 --- a/[core]/es_extended/server/main.lua +++ b/[core]/es_extended/server/main.lua @@ -125,21 +125,18 @@ if not Config.Multichar then return deferrals.done() end - local xPlayerId = xPlayer.playerId - local isExist = DoesPlayerExist(xPlayerId --[[@as string]]) - - if isExist ~= 0 then - deferrals.update(("[ESX] Cleaning old Player entry for [%s] (player invalid)"):format(identifier)) - TriggerEvent('esx:playerDropped', xPlayerId) - ESX.Players[xPlayerId] = nil - Core.playersByIdentifier[identifier] = nil - GlobalState['playerCount'] = GlobalState['playerCount'] - 1 - else + if DoesPlayerExist(xPlayer.source --[[@as string]]) then return deferrals.done( - ("[ESX] There was an error loading your character!\nError code: identifier-active\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same account.\n\nYour identifier: %s"):format(identifier) - ) + ("[ESX] There was an error loading your character!\nError code: identifier-active\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same account.\n\nYour identifier: %s"):format(identifier) + ) end + deferrals.update(("[ESX] Cleaning stale player entry..."):format(identifier)) + TriggerEvent('esx:playerDropped', xPlayer.source) + ESX.Players[xPlayer.source] = nil + Core.playersByIdentifier[identifier] = nil + GlobalState['playerCount'] = GlobalState['playerCount'] - 1 + end) end From 5ed6bf3ebd33087336a3e2a834288a592c489e4c Mon Sep 17 00:00:00 2001 From: Kenshin13 <63159154+Kenshiin13@users.noreply.github.com> Date: Sat, 14 Jun 2025 20:52:16 +0200 Subject: [PATCH 14/23] refactor(es_extended/server/main): use wrapper fun for playerDropped --- [core]/es_extended/server/main.lua | 42 ++++++++++++++++++------------ 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/[core]/es_extended/server/main.lua b/[core]/es_extended/server/main.lua index f81c13e7..a79d16a6 100644 --- a/[core]/es_extended/server/main.lua +++ b/[core]/es_extended/server/main.lua @@ -67,6 +67,29 @@ local function onPlayerJoined(playerId) end end +---@param playerId number +---@param reason string +local function onPlayerDropped(playerId, reason) + local xPlayer = ESX.GetPlayerFromId(playerId) + + if not xPlayer then + return + end + + TriggerEvent("esx:playerDropped", playerId, reason) + local job = xPlayer.getJob().name + local currentJob = Core.JobsPlayerCount[job] + Core.JobsPlayerCount[job] = ((currentJob and currentJob > 0) and currentJob or 1) - 1 + + GlobalState[("%s:count"):format(job)] = Core.JobsPlayerCount[job] + Core.playersByIdentifier[xPlayer.identifier] = nil + + Core.SavePlayer(xPlayer, function() + GlobalState["playerCount"] = GlobalState["playerCount"] - 1 + ESX.Players[playerId] = nil + end) +end + if Config.Multichar then AddEventHandler("esx:onPlayerJoined", function(src, char, data) while not next(ESX.Jobs) do @@ -322,24 +345,9 @@ AddEventHandler("chatMessage", function(playerId, _, message) end end) +---@param reason string AddEventHandler("playerDropped", function(reason) - local playerId = source - local xPlayer = ESX.GetPlayerFromId(playerId) - - if xPlayer then - TriggerEvent("esx:playerDropped", playerId, reason) - local job = xPlayer.getJob().name - local currentJob = Core.JobsPlayerCount[job] - Core.JobsPlayerCount[job] = ((currentJob and currentJob > 0) and currentJob or 1) - 1 - - GlobalState[("%s:count"):format(job)] = Core.JobsPlayerCount[job] - Core.playersByIdentifier[xPlayer.identifier] = nil - - Core.SavePlayer(xPlayer, function() - GlobalState["playerCount"] = GlobalState["playerCount"] - 1 - ESX.Players[playerId] = nil - end) - end + onPlayerDropped(source --[[@as number]], reason) end) AddEventHandler("esx:playerLoaded", function(_, xPlayer) From f28d29cc39976b772a44d8db64a4cecc47e760db Mon Sep 17 00:00:00 2001 From: Kenshin13 <63159154+Kenshiin13@users.noreply.github.com> Date: Sat, 14 Jun 2025 20:53:19 +0200 Subject: [PATCH 15/23] refactor(es_extended/server/main): call playerDropped wrapper for stale player obj --- [core]/es_extended/server/main.lua | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/[core]/es_extended/server/main.lua b/[core]/es_extended/server/main.lua index a79d16a6..3f0b9338 100644 --- a/[core]/es_extended/server/main.lua +++ b/[core]/es_extended/server/main.lua @@ -155,11 +155,7 @@ if not Config.Multichar then end deferrals.update(("[ESX] Cleaning stale player entry..."):format(identifier)) - TriggerEvent('esx:playerDropped', xPlayer.source) - ESX.Players[xPlayer.source] = nil - Core.playersByIdentifier[identifier] = nil - GlobalState['playerCount'] = GlobalState['playerCount'] - 1 - + onPlayerDropped(xPlayer.source, "esx_stale_player_obj") end) end From d892df079f5c311515d12057283c1c93cb71eb00 Mon Sep 17 00:00:00 2001 From: Kenshin13 <63159154+Kenshiin13@users.noreply.github.com> Date: Sat, 14 Jun 2025 20:55:47 +0200 Subject: [PATCH 16/23] resolve deferrals after cleanup --- [core]/es_extended/server/main.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/[core]/es_extended/server/main.lua b/[core]/es_extended/server/main.lua index 3f0b9338..51001d9f 100644 --- a/[core]/es_extended/server/main.lua +++ b/[core]/es_extended/server/main.lua @@ -69,7 +69,7 @@ end ---@param playerId number ---@param reason string -local function onPlayerDropped(playerId, reason) +local function onPlayerDropped(playerId, reason, cb) local xPlayer = ESX.GetPlayerFromId(playerId) if not xPlayer then @@ -84,10 +84,14 @@ local function onPlayerDropped(playerId, reason) GlobalState[("%s:count"):format(job)] = Core.JobsPlayerCount[job] Core.playersByIdentifier[xPlayer.identifier] = nil + local p = promise:new() Core.SavePlayer(xPlayer, function() GlobalState["playerCount"] = GlobalState["playerCount"] - 1 ESX.Players[playerId] = nil + p:resolve() end) + + return Citizen.Await(p) end if Config.Multichar then @@ -156,6 +160,7 @@ if not Config.Multichar then deferrals.update(("[ESX] Cleaning stale player entry..."):format(identifier)) onPlayerDropped(xPlayer.source, "esx_stale_player_obj") + deferrals.done() end) end From b28cf8827388f431646f95d91d24064e92e1d169 Mon Sep 17 00:00:00 2001 From: Kenshin13 <63159154+Kenshiin13@users.noreply.github.com> Date: Sat, 14 Jun 2025 20:57:37 +0200 Subject: [PATCH 17/23] refactor(es_extended/server/main): remove unused event --- [core]/es_extended/server/main.lua | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/[core]/es_extended/server/main.lua b/[core]/es_extended/server/main.lua index 51001d9f..69b42fe6 100644 --- a/[core]/es_extended/server/main.lua +++ b/[core]/es_extended/server/main.lua @@ -388,25 +388,6 @@ AddEventHandler("esx:playerLogout", function(playerId, cb) TriggerClientEvent("esx:onPlayerLogout", playerId) end) -AddEventHandler('esx:playerCrashed', function(identifier, cb) - local xPlayer = ESX.GetPlayerFromIdentifier(identifier) - - if xPlayer then - local playerId = xPlayer.playerId - local isExist = DoesPlayerExist(playerId --[[@as string]]) - - if playerId and isExist ~= 0 then - TriggerEvent('esx:playerDropped', playerId) - GlobalState["playerCount"] = GlobalState["playerCount"] - 1 - Core.playersByIdentifier[identifier] = nil - ESX.Players[playerId] = nil - if cb then - cb() - end - end - end -end) - if not Config.CustomInventory then RegisterNetEvent("esx:updateWeaponAmmo", function(weaponName, ammoCount) local xPlayer = ESX.GetPlayerFromId(source) From 3e0c89d9b20f366b6241240b0b95091566871e6f Mon Sep 17 00:00:00 2001 From: Kenshin13 <63159154+Kenshiin13@users.noreply.github.com> Date: Sat, 14 Jun 2025 21:05:51 +0200 Subject: [PATCH 18/23] feat(es_extended/server/main): add optional cb fun for playerDropped wrapper --- [core]/es_extended/server/main.lua | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/[core]/es_extended/server/main.lua b/[core]/es_extended/server/main.lua index 69b42fe6..9395d9d6 100644 --- a/[core]/es_extended/server/main.lua +++ b/[core]/es_extended/server/main.lua @@ -69,6 +69,7 @@ end ---@param playerId number ---@param reason string +---@param cb function? local function onPlayerDropped(playerId, reason, cb) local xPlayer = ESX.GetPlayerFromId(playerId) @@ -84,15 +85,27 @@ local function onPlayerDropped(playerId, reason, cb) GlobalState[("%s:count"):format(job)] = Core.JobsPlayerCount[job] Core.playersByIdentifier[xPlayer.identifier] = nil - local p = promise:new() + local p = not cb and promise:new() + local function resolve() + if cb then + return cb() + elseif(p) then + return p:resolve() + end + end + Core.SavePlayer(xPlayer, function() GlobalState["playerCount"] = GlobalState["playerCount"] - 1 ESX.Players[playerId] = nil - p:resolve() + resolve() end) - return Citizen.Await(p) + if p then + return Citizen.Await(p) + end end +AddEventHandler("esx:onPlayerDropped", onPlayerDropped) + if Config.Multichar then AddEventHandler("esx:onPlayerJoined", function(src, char, data) @@ -147,7 +160,6 @@ if not Config.Multichar then end local xPlayer = ESX.GetPlayerFromIdentifier(identifier) - if not xPlayer then return deferrals.done() end From 130754dcd2ff014526cd112ff0e0c3eba0215080 Mon Sep 17 00:00:00 2001 From: Kenshin13 <63159154+Kenshiin13@users.noreply.github.com> Date: Sat, 14 Jun 2025 21:06:19 +0200 Subject: [PATCH 19/23] refactor(esx_multicharacter/server/modules/functions): properly cleanup stale player obj --- .../server/modules/functions.lua | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/[core]/esx_multicharacter/server/modules/functions.lua b/[core]/esx_multicharacter/server/modules/functions.lua index b46dd43a..78ef5516 100644 --- a/[core]/esx_multicharacter/server/modules/functions.lua +++ b/[core]/esx_multicharacter/server/modules/functions.lua @@ -49,12 +49,21 @@ function Server:OnConnecting(source, deferrals) if ESX.GetConfig().EnableDebug or not ESX.Players[identifier] then deferrals.done() end - TriggerEvent('esx:playerCrashed', identifier, function() - ESX.Players[identifier] = nil - deferrals.update(('[ESX] Cleaning old Player entry for [%s] (player invalid)'):format(identifier)) - end) + local xPlayer = ESX.GetPlayerFromIdentifier(identifier) + if not xPlayer then + return deferrals.done() + end - deferrals.done() -- proceed + if DoesPlayerExist(xPlayer.source --[[@as string]]) then + return deferrals.done( + ("[ESX] There was an error loading your character!\nError code: identifier-active\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same account.\n\nYour identifier: %s"):format(identifier) + ) + end + + deferrals.update(("[ESX] Cleaning stale player entry..."):format(identifier)) + TriggerEvent("esx:onPlayerDropped", xPlayer.source, "esx_stale_player_obj", function() + deferrals.done() + end) end From 822dbf1dae6f9a59aa02d8e9e78e58cc5cd76c76 Mon Sep 17 00:00:00 2001 From: Kenshin13 <63159154+Kenshiin13@users.noreply.github.com> Date: Sun, 15 Jun 2025 12:57:17 +0200 Subject: [PATCH 20/23] refactor(esx_multicharacter/server/modules/functions): fix deferral prefix --- [core]/esx_multicharacter/server/modules/functions.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/[core]/esx_multicharacter/server/modules/functions.lua b/[core]/esx_multicharacter/server/modules/functions.lua index 78ef5516..1d5a81a6 100644 --- a/[core]/esx_multicharacter/server/modules/functions.lua +++ b/[core]/esx_multicharacter/server/modules/functions.lua @@ -30,7 +30,7 @@ function Server:OnConnecting(source, deferrals) -- luacheck: ignore if not SetEntityOrphanMode then - return deferrals.done(("[ESX] ESX Requires a minimum Artifact version of 10188, Please update your server.")) + return deferrals.done(("[ESX Multicharacter] ESX Requires a minimum Artifact version of 10188, Please update your server.")) end if Server.oneSync == "off" or Server.oneSync == "legacy" then @@ -56,11 +56,11 @@ function Server:OnConnecting(source, deferrals) if DoesPlayerExist(xPlayer.source --[[@as string]]) then return deferrals.done( - ("[ESX] There was an error loading your character!\nError code: identifier-active\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same account.\n\nYour identifier: %s"):format(identifier) + ("[ESX Multicharacter] There was an error loading your character!\nError code: identifier-active\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same account.\n\nYour identifier: %s"):format(identifier) ) end - deferrals.update(("[ESX] Cleaning stale player entry..."):format(identifier)) + deferrals.update(("[ESX Multicharacter] Cleaning stale player entry..."):format(identifier)) TriggerEvent("esx:onPlayerDropped", xPlayer.source, "esx_stale_player_obj", function() deferrals.done() end) From 834e6d5cbae2afc86d866b2e389beaca4708d0f5 Mon Sep 17 00:00:00 2001 From: Kenshin13 <63159154+Kenshiin13@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:02:47 +0200 Subject: [PATCH 21/23] fix(esx_multicharacter/server/modules/functions): store formatted identifier --- [core]/esx_multicharacter/server/modules/functions.lua | 10 ++++++++-- .../server/modules/multicharacter.lua | 10 ++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/[core]/esx_multicharacter/server/modules/functions.lua b/[core]/esx_multicharacter/server/modules/functions.lua index 1d5a81a6..8f9ccd4c 100644 --- a/[core]/esx_multicharacter/server/modules/functions.lua +++ b/[core]/esx_multicharacter/server/modules/functions.lua @@ -16,7 +16,7 @@ function Server:ResetPlayers() table.wipe(ESX.Players) for _, v in pairs(players) do - ESX.Players[self:GetIdentifier(v.source)] = true + ESX.Players[self:GetIdentifier(v.source)] = v.identifier end else ESX.Players = {} @@ -49,7 +49,13 @@ function Server:OnConnecting(source, deferrals) if ESX.GetConfig().EnableDebug or not ESX.Players[identifier] then deferrals.done() end - local xPlayer = ESX.GetPlayerFromIdentifier(identifier) + if ESX.Players[identifier] == true then + return deferrals.done( + ("[ESX Multicharacter] There was an error loading your character!\nError code: identifier-active\n\nThis error is caused by a player on this server who has the same identifier as you have. Make sure you are not playing on the same account.\n\nYour identifier: %s"):format(identifier) + ) + end + + local xPlayer = ESX.GetPlayerFromIdentifier(ESX.Players[identifier]) if not xPlayer then return deferrals.done() end diff --git a/[core]/esx_multicharacter/server/modules/multicharacter.lua b/[core]/esx_multicharacter/server/modules/multicharacter.lua index c43be581..25165c3b 100644 --- a/[core]/esx_multicharacter/server/modules/multicharacter.lua +++ b/[core]/esx_multicharacter/server/modules/multicharacter.lua @@ -78,18 +78,20 @@ function Multicharacter:CharacterChosen(source, charid, isNew) end end - TriggerEvent("esx:onPlayerJoined", source, ("%s%s"):format(Server.prefix, charid)) - ESX.Players[Server:GetIdentifier(source)] = true + local charIdentifier = ("%s%s"):format(Server.prefix, charid) + TriggerEvent("esx:onPlayerJoined", source, charIdentifier) + ESX.Players[Server:GetIdentifier(source)] = charIdentifier end end function Multicharacter:RegistrationComplete(source, data) local charId = self.awaitingRegistration[source] + local charIdentifier = ("%s%s"):format(Server.prefix, charId) self.awaitingRegistration[source] = nil - ESX.Players[Server:GetIdentifier(source)] = true + ESX.Players[Server:GetIdentifier(source)] = charIdentifier SetPlayerRoutingBucket(source, 0) - TriggerEvent("esx:onPlayerJoined", source, ("%s%s"):format(Server.prefix, charId), data) + TriggerEvent("esx:onPlayerJoined", source, charIdentifier, data) end function Multicharacter:PlayerDropped(player) From e524ed13af1c7eadea575595de001918359cddb0 Mon Sep 17 00:00:00 2001 From: Kenshin13 <63159154+Kenshiin13@users.noreply.github.com> Date: Sun, 15 Jun 2025 13:34:18 +0200 Subject: [PATCH 22/23] fix(esx_multicharacter/server/modules/functions): mark palyer as connected on cleanup --- [core]/esx_multicharacter/server/modules/functions.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/[core]/esx_multicharacter/server/modules/functions.lua b/[core]/esx_multicharacter/server/modules/functions.lua index 8f9ccd4c..6afd966e 100644 --- a/[core]/esx_multicharacter/server/modules/functions.lua +++ b/[core]/esx_multicharacter/server/modules/functions.lua @@ -68,6 +68,7 @@ function Server:OnConnecting(source, deferrals) deferrals.update(("[ESX Multicharacter] Cleaning stale player entry..."):format(identifier)) TriggerEvent("esx:onPlayerDropped", xPlayer.source, "esx_stale_player_obj", function() + ESX.Players[identifier] = true deferrals.done() end) end From e1597110dbb8c10c426e05ae861eb386510e1ce8 Mon Sep 17 00:00:00 2001 From: Kenshin13 <63159154+Kenshiin13@users.noreply.github.com> Date: Sun, 15 Jun 2025 14:05:10 +0200 Subject: [PATCH 23/23] fix(esx_multicharacter/server/modules/functions): build proper identifier --- [core]/esx_multicharacter/server/modules/functions.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/[core]/esx_multicharacter/server/modules/functions.lua b/[core]/esx_multicharacter/server/modules/functions.lua index 6afd966e..a5578575 100644 --- a/[core]/esx_multicharacter/server/modules/functions.lua +++ b/[core]/esx_multicharacter/server/modules/functions.lua @@ -47,7 +47,10 @@ function Server:OnConnecting(source, deferrals) if not identifier then return deferrals.done(("[ESX Multicharacter] Unable to retrieve player identifier.\nIdentifier type: %s"):format(Server.identifierType)) end - if ESX.GetConfig().EnableDebug or not ESX.Players[identifier] then deferrals.done() end + if ESX.GetConfig().EnableDebug or not ESX.Players[identifier] then + ESX.Players[identifier] = true + return deferrals.done() + end if ESX.Players[identifier] == true then return deferrals.done( @@ -55,8 +58,9 @@ function Server:OnConnecting(source, deferrals) ) end - local xPlayer = ESX.GetPlayerFromIdentifier(ESX.Players[identifier]) + local xPlayer = ESX.GetPlayerFromIdentifier(("%s:%s"):format(ESX.Players[identifier], identifier)) if not xPlayer then + ESX.Players[identifier] = true return deferrals.done() end