How would I counteract player removing function running before :BindToClose()?

In my game when someone leaves, it checks to see if they are in a game, if so then they get their data changed to where it gives them a loss.

My issue is when I shutdown the server and attempt to use :BindToClose() the Player Removing function runs before :BindToClose(). But obviously when I’m shutting down I don’t want to give the person a loss so is there any way I combat this?

Kind of hacky, but you could store the player’s UserId in a table, with os.time() of when the player leaves, then when :BindToClose() runs, check the table to see who has recently left, and if it’s within let’s say 3 seconds (arbitrary number, use what you think fits), then it will alter the player’s data to count that as a win.

For example:
(UNTESTED CODE)

local playerTable = {}

game.Players.PlayerRemoving:Connect(function(Player) 
    playerTable[Player.UserId] = os.time()
end)

game:BindToClose(function()
    local currentTime = os.time()

    for i,v in pairs(playerTable) do
        if os.difftime(currentTime, v) < 3 then -- checks if the player left less than 3 seconds ago
            -- save data!
        end
    end
end)

I do apologize if there is a better way to do this, I am not all too familiar with the execution order of closing events.

Let me know how you make out.

2 Likes

Ya but thats why I’m having the issue, if there are say for example 5 players in the server, 1 leaves while they are currently in the game, their data won’t save because the :BindToClose function will not run.

But it got me thinking, how long does it take :BindToClose to run after the shutdown button has been pressed?

In the PlayerRemoving handler, you could task.delay the “count as a loss” function by about a minute.

That way, if the server shuts down before that scheduled task runs, no loss is counted.

If a player leaves more than a minute before the server shuts down, the scheduled task runs as normal and their leave counts as a loss.

The only problem with this method is that when a server shuts down, it has 30 seconds until it forcibly shuts down, so if you want a minute, there is potential for data loss.

Another thing you could do (similar to your method, just different) is to have a while wait() do loop which checks if a variable set by :BindToClose() is actually set.
For example: (also untested)

local shuttingDown = false

game.Players.PlayerRemoving:Connect(function(Player) 
    local waitTime = 0

    while waitTime < 30 and not shuttingDown do -- wait for 30 seconds and check if server is note shutting down
        wait(.01)
        waitTime += .01
    end -- You could put this into a task.spawn() function and have this running in the background, while you serialize all your data to save
end)

game:BindToClose(function()
    shuttingDown = true
end)

Sorry for the late reply.

1 Like