A few months ago I created a Datastore script that saves several bool values for the player under one Key. People were reporting to me quite frequently that they had lost their save, so my solution was to add a pcall function to catch an error if the datastore script fails for any reason, and retry the code to make sure the player’s data saves for any reason, whether it be a crash or the server goes down.
I thought this fixed the problem, but I still have several players reporting that they lost their entire save. I looked up solutions to this, and I learned that there were problems on Roblox’s end with datastores, and I followed the thread closely, and when it was confirmed fixed, I was relieved, but still weeks after the fix players report data loss. It might have something to do with my script then.
This is the entire script that handles the data. There is one key for everything, and it loads when the player joins, and saves when the player leaves.
The context for the data loss is that the entire player’s save file is not there, and I get a print saying that the player has no data yet, so I’m thinking it has something to do with an error happening with GetAsync(). I added a print to warn me if an error occurred, and when I see data loss on myself, (It happens to me maybe once out of every 20(approximate) times I join, which is not good) and I see no print errors about an error getting a save, I simply get an error saying I have no data yet.
This is a Server Script inside of ServerScriptService. This is what the ancestry looks like:
Help would be so appreciated!!
local PlayerSavedData = game:GetService('DataStoreService'):GetDataStore("PLAYERSAVEFILE")
local RunService = game:GetService("RunService")
local moneygain = 120
local errordebounce = 6
game.Players.PlayerAdded:connect(function(player)
repeat wait() until script:FindFirstChild("PlayerSave")
local save = script.PlayerSave:Clone()
save.Parent = player
local amount = save:WaitForChild("Amount")
while wait(moneygain) do
if amount.Value < 5000 then
amount.Value = amount.Value+5
end
end
end)
function BirdsDataTable(player)
local BirdInventory = {
Amount = player.PlayerSave.Amount.Value,
Peafowl = player.PlayerSave.Peafowl.Value,
Parrot = player.PlayerSave.Parrot.Value,
Ostrich = player.PlayerSave.Ostrich.Value,
Penguin = player.PlayerSave.Penguin.Value,
Puffin = player.PlayerSave.Puffin.Value,
Toucan = player.PlayerSave.Toucan.Value,
Flamingo = player.PlayerSave.Flamingo.Value,
Falcon = player.PlayerSave.Falcon.Value,
Owl = player.PlayerSave.Owl.Value,
Vulture = player.PlayerSave.Vulture.Value,
Eagle = player.PlayerSave.Eagle.Value
}
return BirdInventory
end
function SaveData(player)
local Success,Error = pcall(function()
local playerkey = "player-"..player.userId
local data = BirdsDataTable(player)
PlayerSavedData:SetAsync(playerkey,data)
end)
if Error then
print("***ERROR SAVING DATA FOR "..player.Name)
local attempts = 0
while wait (errordebounce) do
local retries = attempts + 1
attempts = retries
local pass,fail = pcall(function()
local playerkey = "player-"..player.userId
local data = BirdsDataTable(player)
PlayerSavedData:SetAsync(playerkey,data)
print("Successfully saved data for "..player.Name)
end)
if pass or attempts == 10 then break end
end
end
end
game.Players.PlayerAdded:connect(function(player)
repeat wait() until player.Character
repeat wait() until player:FindFirstChild("PlayerSave")
local PS = player.PlayerSave
local data = BirdsDataTable(player)
local playerkey = "player-"..player.userId
local Passed, Error = pcall(function()
local SaveFiles = PlayerSavedData:GetAsync(playerkey)
if SaveFiles == nil then
print(player.Name.." has no data yet.")
else
PS.Amount.Value = SaveFiles.Amount
PS.Peafowl.Value = SaveFiles.Peafowl
PS.Parrot.Value = SaveFiles.Parrot
PS.Ostrich.Value = SaveFiles.Ostrich
PS.Penguin.Value = SaveFiles.Penguin
PS.Puffin.Value = SaveFiles.Puffin
PS.Toucan.Value = SaveFiles.Toucan
PS.Flamingo.Value = SaveFiles.Flamingo
PS.Falcon.Value = SaveFiles.Falcon
PS.Owl.Value = SaveFiles.Owl
PS.Vulture.Value = SaveFiles.Vulture
PS.Eagle.Value = SaveFiles.Eagle
end
end)
if Error then
print("***ERROR GETTING SAVE FILE FOR "..player.Name)
local attempts = 0
while wait(errordebounce) do
local retries = attempts + 1
attempts = retries
local pass,err = pcall(function()
local SaveFiles = PlayerSavedData:GetAsync(playerkey)
if SaveFiles == nil then
print(player.Name.." has no save data yet")
else
PS.Amount.Value = SaveFiles.Amount
PS.Peafowl.Value = SaveFiles.Peafowl
PS.Parrot.Value = SaveFiles.Parrot
PS.Ostrich.Value = SaveFiles.Ostrich
PS.Penguin.Value = SaveFiles.Penguin
PS.Puffin.Value = SaveFiles.Puffin
PS.Toucan.Value = SaveFiles.Toucan
PS.Flamingo.Value = SaveFiles.Flamingo
PS.Falcon.Value = SaveFiles.Falcon
PS.Owl.Value = SaveFiles.Owl
PS.Vulture.Value = SaveFiles.Vulture
PS.Eagle.Value = SaveFiles.Eagle
print("Successfully got saved data for "..player.Name)
end
end)
if pass or attempts == 10 then break end
end
end
if PS.Amount.Value < 0 then
PS.Amount.Value = 100
end
end)
game.Players.PlayerRemoving:Connect(SaveData)
game:BindToClose(function()
if RunService:IsStudio() then return end
local Players = game:GetService("Players")
for _,player in pairs(Players:GetPlayers()) do
SaveData(player)
print("Saved data for "..player.Name.." on shutdown.")
end
end)