diff --git a/[core]/es_extended/server/main.lua b/[core]/es_extended/server/main.lua index 845bc7e9..48251143 100644 --- a/[core]/es_extended/server/main.lua +++ b/[core]/es_extended/server/main.lua @@ -67,6 +67,46 @@ local function onPlayerJoined(playerId) end end +---@param playerId number +---@param reason string +---@param cb function? +local function onPlayerDropped(playerId, reason, cb) + 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 + + 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 + resolve() + end) + + if p then + return Citizen.Await(p) + end +end +AddEventHandler("esx:onPlayerDropped", onPlayerDropped) + + if Config.Multichar then AddEventHandler("esx:onPlayerJoined", function(src, char, data) while not next(ESX.Jobs) do @@ -115,17 +155,24 @@ 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 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 + + local xPlayer = ESX.GetPlayerFromIdentifier(identifier) + if not xPlayer then + return deferrals.done() + end + + 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)) + onPlayerDropped(xPlayer.source, "esx_stale_player_obj") + deferrals.done() end) end @@ -311,24 +358,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) diff --git a/[core]/esx_multicharacter/server/modules/functions.lua b/[core]/esx_multicharacter/server/modules/functions.lua index 8792cec1..a5578575 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 = {} @@ -27,10 +27,10 @@ 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.")) + 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 @@ -45,19 +45,37 @@ 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 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)) + 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 + ESX.Players[identifier] = true + return deferrals.done() end + + 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(("%s:%s"):format(ESX.Players[identifier], identifier)) + if not xPlayer then + ESX.Players[identifier] = true + return deferrals.done() + end + + if DoesPlayerExist(xPlayer.source --[[@as string]]) 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 + + 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 + Server:ResetPlayers() 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)