Those waits are pointless. The server will close down the moment your operations finish, they don’t stall how long the server stays up for.
Don’t kick every player from the server from BindToClose: not only is this not the intended use of BindToClose, but it is also grossly unnecessary because all players will already be gone from the server. You should instead implement data saving techniques for leftover data sets that the server still tracks.
As well, two things about your loop:
While what variable names you use for the for loop don’t quite matter, you have the standard variable convention in reverse. The i should come first as it stands for index.
Where did people learn this unreadable way of writing for loops with in next? Use a proper generator. GetPlayers returns an array, so use ipairs to iterate over it.
userId is deprecated in favour of UserId for the sake of naming convention consistency. All properties follow PascalCase convention and their camelCase variants are deprecated. Yes UserId should be capitalised but in the sense that you’re using the current correct property rather than the old one.
So I’ve had this problem before! The way to do this is instead of leaving the game in-studio, you have to kick the player from the game in the command line.
This is because in the studio, when you leave/stop the game, the server and the client shutdown at the same time! This is a problem because if the server shuts down before saving the data won’t save!
If you kick the player instead, the server is still running because the player still has that kicked message. That’s why the server is able to save the data!
Heres the line you should write in the client’s command line in the studio
I don’t remember if I ever fixed this particular issue but it’s probably best to use something like ProfileService for data saving because it handles all the edge-cases for you.
The problem that I could see is it needed to save to a boolValue or something for it to setAsync.
local DataStoreService = game:GetService("DataStoreService")
local PetDataStore = DataStoreService:GetDataStore("Pets")
game.Players.PlayerAdded:Connect(function(player)
local success, petData = pcall(function()
return PetDataStore:GetAsync(player.UserId)
end)
if success then
local boolVal = Instance.new("BoolValue", player)
boolVal.Name = "Pet"
boolVal.Value = petData or "normalPet"
else
warn("Failed to retrieve pet data for player " .. player.Name)
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local boolVal = player:FindFirstChild("Pet")
if boolVal then
local success, err = pcall(function()
PetDataStore:SetAsync(player.UserId, boolVal.Value)
end)
if not success then
warn("Failed to save pet data for player " .. player.Name .. ": " .. err)
end
end
end)