Trying to save/load cash (datastore)

so when a player joins a game, if they have cash already saved; i want to load their cash. if they have no data then i want their cash to be 100,000. im trying to load and save the players cash.

when i join the game the cash ends up being 0 instead of 100,000 and yeah that’s the problem. i only started working with datastore today so i appreciate any help tysm!!

code:

local dss = game:GetService("DataStoreService")
local cash_data = dss:GetDataStore("cash_data")

--player join
function module.LeaderboardandLoadData(p:Player)
	local leaderstats = Instance.new("Folder", p)
	leaderstats.Name = "leaderstats"
	local Cash = Instance.new("IntValue", leaderstats)
	Cash.Name = "Cash"
	local data
	local success, err = pcall(function()
		data = cash_data:GetAsync(p.UserId)
	end)

	if success then
		Cash.Value = data
	else
		Cash.Value = 10000
	end
end

--player leave
function module.SavePlayerData(p)
	local leaderstats = p:WaitForChild("leaderstats")
	local Cash = leaderstats:FindFirstChild("Cash")
	local success, err = pcall(function()
		cash_data:SetAsync(p.UserId, Cash.Value)
	end)
	if success then
		print("data saved for: "..p.Name)
	else
		warn("error saving data for: "..p.Name)
	end
end

problem lies with the if statement.
If a :GetAsync(key) has no data it will simply return nil. Not an error.

1 Like

hey torch, ty for ur help.

if the problem is with the if statement, how would you make sure to apply cash to the players cash value if there is no data?

i tried something like this but yea that doesnt work either.

	if success then
		if data ~= nil then
			Cash.Value = data
		else
			Cash.Value = 10000
		end
	else
		warn("Error loading data for player: ", err)
	end

If a :GetAsync() call fails you want to try again.
However, you can run into API Rate limits if not properly handled, but in this case it should be fine and you should not have to worry about rate limits.

did you publish your game??? Sometimes data isnt save in roblox studio so you might also want to try in roblox client instead of roblox studio

1 Like

Data is always saved in DataStores even if it’s studio.

yeah i tried testing again, publishing and even tried by playing roblox itself, it just sets my cash as 0 when i join. its really weird because i did a 2 player test. one player has 10,000; the other has 0.

thats good to knowtho, i appreciate it. ty for the info.

just an update

i renamed the data store variable to like “Jjjj” or something and named it back and its loading in the cash fine now. i just have an issue with saving. it doesnt save the cash unfortunately.

local cash_data = dss:GetDataStore("cashData")

it prints saying the data was saved but it wasnt thats the thing :triumph:
image

When the player has no data, the getasync call won’t fail/error, so success will be true. You would have to check explicitly that they have no data, eg:

local success, err = pcall(function()
	data = cash_data:GetAsync(p.UserId)
end)

if success then
	Cash.Value = data or 100000

    -- or use an if-statement (if data then value = data else value = 100000)
else
    -- handle the request failing
end
2 Likes

Can I see the code you’re using to save cash?

1 Like

ill keep that in mind ty for the help cody. i did a similar check earlier but ill try that. loading is working so far tho

1 Like

yes. that was my saving function:

--player leave
function module.SavePlayerData(p)
	local leaderstats = p:WaitForChild("leaderstats")
	local Cash = leaderstats:FindFirstChild("Cash")
	local success, err = pcall(function()
		cash_data:SetAsync(p.UserId, Cash.Value)
	end)
	if success then
		print("data saved for: "..p.Name)
	else
		warn("error saving data for: "..p.Name)
	end
end

Are you saving player data on game:BindToClose() and auto saving every 60~ seconds?

im saving the player data immediately as the player leaves. not really sure what u mean for auto saving tho.

i used this video as a reference:

so this is my server code:

game.Players.PlayerRemoving:Connect(function(p)
	leaderboard_module.SavePlayerData(p)
end)

game:BindToClose(function()
	leaderboard_module.ExtendServerExitTime()
end)

and the module with the bindtoclose:

--player leave
function module.SavePlayerData(p)
	local leaderstats = p:WaitForChild("leaderstats")
	local Cash = leaderstats:FindFirstChild("Cash")
	local success, err = pcall(function()
		cash_data:SetAsync(p.UserId, Cash.Value)
	end)
	if success then
		print("data saved for: "..p.Name)
	else
		warn("error saving data for: "..p.Name)
	end
end

function module.ExtendServerExitTime()
	warn("WARNING: server shutting down! saving player data...")
	task.wait(3)
	warn("server shutting down!")
end

The problem is that you aren’t saving the players data when the server shuts down.
Which is what game:BindToClose() does.
Your :BindToClose() should look like

game:BindToClose(function()
	for _, Player in game.Players:GetPlayers() do
		leaderboard_module.SavePlayerData(Player)
	end
end)

Saving 2 times on the PlayerRemoving and Shutting down IS NOT a good practice, Extending the time should actually fix that without doing unnecessary saves.


@targetframed
Try this for quick debugging.

function module.SavePlayerData(p)
	local leaderstats = p:FindFirstChild("leaderstats")
	local Cash = leaderstats:FindFirstChild("Cash")
	local success, err = pcall(function()
		cash_data:SetAsync(p.UserId, Cash.Value)
	end)
	if success then
		print("data saved for: "..p.Name)
	else
		warn("error saving data for: "..p.Name.." Error:", err)
	end
end

You also gotta make sure you have the API Services enabled so the data can be saved.

1 Like

hey smokin, thanks for your help mate.

i ran the code you provided and its printing saying that the data was saved in the output but when i join back it just reverts to the initial 10k. i have API services enabled btw

Is the data being updated on client?

1 Like

i’m saving and loading the data via server script