My Datastore does not work; I need help

local ds = game:GetService("DataStoreService")
local cash = ds:GetDataStore("") -- left blank for security reasons

game.Players.PlayerAdded:Connect(function(plr)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = plr
	
	local coins = Instance.new("IntValue")
	coins.Parent = leaderstats
	coins.Name = "Coins"
	
	if cash:GetAsync(plr.UserId) == nil then
		coins.Value = 0
		cash:SetAsync(plr.UserId, coins.Value)
	else
	    coins.Value = cash:GetAsync(plr.UserId)
end
end)

game.Players.PlayerRemoving:Connect(function(plr)
	local success, err = pcall(function()
		cash:SetAsync(plr.UserId, plr.leaderstats.Coins.Value)
	end)
	if success then
		print(success)
	else
		warn(err)
	end
end)

This is my DataStore which I made. I spent half an hour writing and learning the code, but suddenly it does not work. When it fails to save the coins, I get no error. I really need some help.

1 Like

Hey there. I threw your code into a place and found it to be working perfectly as intended. I’ve heard that sometimes PlayerRemoving will fail to fire if a player crashes, or you may have issues saving when a game shuts down if you don’t account for it. So here’s how I would modify your code to be more resilient.

local ds = game:GetService("DataStoreService")
local cash = ds:GetDataStore("MyDataStore") 
local AUTOSAVE_INTERVAL = 120

local function savePlayerData(plr)
	local success, err = pcall(function()
		cash:SetAsync(plr.UserId, plr.leaderstats.Coins.Value)
	end)
	if success then
		print(success)
	else
		warn(err)
	end    
end    

local function playerAdded(plr)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = plr
	
	local coins = Instance.new("IntValue")
	coins.Name = "Coins"
	
	if cash:GetAsync(plr.UserId) == nil then
		coins.Value = 0
		cash:SetAsync(plr.UserId, coins.Value)
	else
	    coins.Value = cash:GetAsync(plr.UserId)
    end
    coins.Parent = leaderstats
    -- autosave
    delay(AUTOSAVE_INTERVAL, function()
        while plr and plr.Parent do
            savePlayerData(plr)
            wait(AUTOSAVE_INTERVAL)
        end    
    end)
end    

game.Players.PlayerAdded:Connect(playerAdded)
game.Players.PlayerRemoving:Connect(savePlayerData)
-- make sure all players save before the server shuts down
game:BindToClose(function() 
    for _, plr in pairs(game.Players:GetPlayers()) do
        savePlayerData(plr)
    end
end)

BTW- there’s no reason for you to block out your DataStore name. We can’t do anything with it :wink:

8 Likes

Will the autosave crash my game? Sometimes when I use forever loops the game crashes.

EDIT:

OOF, I thought people could try to change values in a datastore.

1 Like

There are a lot of issues here that I can see from just taking a glance. Most importantly your GetAsync() should be wrapped using a pcall. You face the risk of data wipes if GetAsync() fails which is a serious concern your current implementation does not take into consideration. Also, do not spam :GetAsync() and :SetAsync() functions. You are going to throttle DataStore limits very quickly that way.

if cash:GetAsync(plr.UserId) == nil then
	coins.Value = 0
	cash:SetAsync(plr.UserId, coins.Value)
else
    coins.Value = cash:GetAsync(plr.UserId)
end
1 Like

Don’t worry, I’ve set this loop up to terminate when the player leaves. It won’t run infinitely.

2 Likes

This is a great point as well that I missed. An easy fix to prevent data corruption is to not parent the coins value to leaderstats until after you’ve confirmed GetAsync ran without error. This might cause issues for that player, but it’ll prevent data loss. Ideally you want to continuously re-try GetAsync if it fails. I’ve edited my code example above with the easier fix

3 Likes

Thanks! I got one last question though. Is there a way to retrieve wiped datastore information, if not, should I save all my data to a database in case of an attack or function fail?

No, unless you have a backup copy stored somewhere else. Wipe the data once and it’s gone.

There are other avenues you can take such as using DataStore2, but, honestly, they aren’t necessary as long as you write your code properly with security in mind.

1 Like

I have the same problem - my datastore uses PlayerRemoving and it takes 4 or 5 tries for it to save in studio

That’s because studio closes so quickly that it doesn’t have time to save. Though, I have tried holding down the stop button and it will sometimes work.