Player removing firing with BindToClose

I am having an issue in my game, where sometimes, when the last player leaves, it runs both the player removing and game:BindToClose functions. This is a problem as this causes datastore requests to max out, causing players to lose data. Here is the code:

game.Players.PlayerRemoving:Connect(function(plr)
	SaveData(plr)
end)

game:BindToClose(function()
	for i, plr in pairs(game.Players:GetPlayers()) do
		SaveData(plr)
	end
end)
4 Likes

Check if theres more than 1 player ingame inside the PlayerRemoving event.

2 Likes

If the last player leaves and there are no players left in the game, it’s going to shut down. So when the last player leaves it’s obviously going to fire the BindToClose event. You should check if there are any players left in the game before trying to save their data. Maybe add a variable to the player that sets to true once their data has been saved and then check in the next SaveData function if it has been saved or not, and only save again if it hasn’t.

to prevent the data loss from happening, you have to check if there’s no players left in the game, as @CZXPEK and @WoTrox already said.

try using this code instead.

check = function()
	if #game:GetService("Players"):GetPlayers() == 1 then
		return false
	else
		return true
	end
end
game.Players.PlayerRemoving:Connect(function(plr)
	if check() == true then
		SaveData(plr)	
	end
end)

game:BindToClose(function()
	for i, plr in pairs(game.Players:GetPlayers()) do
		SaveData(plr)
	end
end)
2 Likes

Perhaps an attribute debounce? The first thing that comes to mind is adding the player to a table or assigning an attribute to the player and removing it after several seconds to prevent multiple save attempts.


local Saving = {}

game.Players.PlayerRemoving:Connect(function(plr)
	
	if table.find(Saving, plr) then return end
	 
	table.insert(Saving, plr)

	task.delay(5, -- time before the player can save again
	table.remove(Saving, table.find(Saving, plr))
	)

	SaveData(plr)
end)

game:BindToClose(function()

	for i, plr in pairs(game.Players:GetPlayers()) do

		if table.find(Saving, plr) then continue end
	 
		table.insert(Saving, plr)

		task.delay(5, -- time before the player can save again
		table.remove(Saving, table.find(Saving, plr))
		)

		SaveData(plr)
	end

end)

Or I reccommend ProfileService, a great datastore module that has already ironed all of these issues, with autosave and saving on bindtoclose.

When a server is shut down, does the player removing function run for all players? As I am using the BindToClose to prevent dataloss on server shutdowns.

Yes, session locking would help. I recommend profileservice, but if you only want a fix to your issue:

Keep track of wether a save is currently in progress for a player. This can be a simple array of player indices, and boolean values. Then at the beginning of the ‘SaveData’ function you don’t save if this value is set to true. Before the save async call, you set that value to true, and after the async call, set it back to false.

If this still doesn’t fix it, you can use a debounce.

I don’t think I can switch the datastore2 as I already have datastores for players.

I am testing this possible solution and so far it seems to be working.

1 Like

maybe something simple like would work
edit: i saw @CremaCoffeeOverseer ddid the same thing

local UpdatedInTheLast5Seconds = {}
game.Players.PlayerRemoving:Connect(function(plr)
	if table.find(UpdatedInTheLast5Seconds, plr.Name) then return end
	table.insert(UpdatedInTheLast5Seconds,plr)
	SaveData(plr)
	wait(5)
	table.remove(table.find(UpdatedInTheLast5Seconds, plr.Name))
end)

game:BindToClose(function()
	for i, plr in pairs(game.Players:GetPlayers()) do
		if table.find(UpdatedInTheLast5Seconds, plr.Name) then return end
		table.insert(UpdatedInTheLast5Seconds,plr)
		SaveData(plr)
		wait(5)
		table.remove(table.find(UpdatedInTheLast5Seconds, plr.Name))
	end
end)

This seems to be the simpelist solution! Thanks, and thanks to everyone that tried to help! I greatly appreciate it!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.