Saving Data Issue

local function save(player)
	PennyStore:SetAsync(player.UserId,player:WaitForChild("Values"):WaitForChild("Pennies").Value)
	NickelStore:SetAsync(player.UserId,player:WaitForChild("Values"):WaitForChild("Nickels").Value)
	DimeStore:SetAsync(player.UserId,player:WaitForChild("Values"):WaitForChild("Dimes").Value)
	QuarterStore:SetAsync(player.UserId,player:WaitForChild("Values"):WaitForChild("Quarters").Value)
	DollarStore:SetAsync(player.UserId,player:WaitForChild("Values"):WaitForChild("Dollars").Value)
	FiveDollarStore:SetAsync(player.UserId,player:WaitForChild("Values"):WaitForChild("FiveDollars").Value)
	TenDollarStore:SetAsync(player.UserId,player:WaitForChild("Values"):WaitForChild("TenDollars").Value)
	TwentyDollarStore:SetAsync(player.UserId,player:WaitForChild("Values"):WaitForChild("TwentyDollars").Value)
	FiftyDollarStore:SetAsync(player.UserId,player:WaitForChild("Values"):WaitForChild("FiftyDollars").Value)
	HundredDollarStore:SetAsync(player.UserId,player:WaitForChild("Values"):WaitForChild("HundredDollars").Value)
end
game:BindToClose(function()
	for _,client in ipairs(game:GetService("Players"):GetPlayers()) do
		spawn(function()
			save(client)
		end)
	end
end)
game.Players.PlayerRemoving:Connect(function(player)
	save(player)
end)

This does not save, and nothing appears in the output. API services are turned on.

1 Like

First of all, you dont need WaitForChild() with SetAsync.
Second (my eyes.)… instead of using 1 datastore for every currency just make a function like Player_stats
create a table called playerstats then loop through the player’s folder which has the currency then you add the currency into playerstats, then return it.
When the player is leaving you can just call the function and save it’s properties.
Kinda like this, i’m not good at explaining :frowning:

this is for storing all the values in a table

local function createdata(player)
	local player_stats = {}
	for _,stat in pairs(player.leaderstats:GetChildren()) do
		player_stats[stat.Name] = stat.Value
	end
	return player_stats
end

this is for saving.

local function onremove(player)
	local playerstats = createdata(player)
	local success,errormsg = pcall(function()
		local playerid = "Player"..player.UserId
		savedata:SetAsync(playerid,playerstats)
	end)
	if success then
		print("Data Has Been Saved")
	else
		warn(errormsg)
	end
end

wdym, im confused. Can you give an actual event code sample? like game.players.playeradded:connect etc

This is like one of the easiest things to do, there are bunch of tutorials on youtube about this. You can go watch them.

local DataStore = game:GetService("DataStoreService")
local Players = game:GetService("Players")

function GetSaved(plr)
	for i,v in pairs(script:GetChildren()) do 
		local d = DataStore:GetDataStore(v.Name)
		local x = Instance.new("NumberValue",plr.Values)
		x.Name = v.Name
		x.Value = d:GetAsync(plr.UserId) or v.Value
	end
end

function Saved(player)
	for i,v in pairs(script:GetChildren()) do 
		local d = DataStore:GetDataStore(v.Name)
		d:SetAsync(player.UserId, player.Values[v.Name].Value)
	end
end

local function playerAdded(plr)
	plr.CharacterAppearanceLoaded:Connect(function(character)
		if plr and plr.Character and plr.Character == character then	
			local leader = Instance.new("Folder",plr)
			leader.Name = "Values"
			GetSaved(plr)
			
			game:BindToClose(function()
				Saved(plr)
			end)
		end
	end)
end

for _, player in pairs(Players:GetPlayers()) do 
	playerAdded(player)
end

Players.PlayerAdded:Connect(playerAdded)

game.Players.PlayerRemoving:Connect(function(player)
	Saved(player)
end)

All you to do is add ‘Number Value’ ​​inside the script

I see no need to have a seperate datastore for each type of currency. You should only have one datastore, and then just set Pennies, Nickels, etc inside of a table or dictionary and save that to the datastore. It will make saving and retrieving data much easier.

Also, you should always wrap get and set asyncs inside of a pcall. Datastores are prone to catching, and you always need to make sure you can catch it so you can retry.

I think I also see your issue: the data is located inside the player. This is an issue because when the player leaves, the data will also be gone meaning it can’t get anything to save off of. I reccomend you save your data in ReplicatedStorage I believe is best, so the client can retrieve it without calling the function, and can’t edit it because of filtering enabled.

I reccomend you stay away from calling a separate GetDataStore for every username, and instead use one GetDataStore for all data, because when setting or getting data you use a key which already separates it. Also with the way you have it set up, a players data will get wiped whenever their name changes because you call a separate datastore instance for there name. Easiest way around that is to use only 1 GetSataStore for everyone.

I also reccomend you wrap your SetAsync and GetAsync in a pcall, because datastore service is not perfect and can catch and fail, and you need to get when it fails so you can retry.

1 Like

What im trying to say, is how do you save a table.

Could you please make an example of saving a string

I suggest using one data store to save all of this data in a table for each player. Here is some sample code that I came up with real quick for saving:

local playerValues = plr:WaitForChild("Values")
local pennies = playerValues:WaitForChild("Pennies")
local nickles = playerValues:WaitForChild("Nickels")

local toSave = {pennies.Value, nickles.Value}
local success, message = pcall(function()
      StatsData:SetAsync(plr.UserId, toSave)
end)

if not success then
   print(message)
end

As for loading the data in, you simply retrieve the data and then set the values.

local data 
local success, message = pcall(function()
      data = StatsData:GetAsync(plr.UserId)
end

if data then
    pennies.Value = data[1]
    nickles.Value = data[2]
end

if not success then
  print(message)
end

Of course, you need to define the data store and do other things, but that is a general outline for how to save with tables. If you want to add more values, simply add more to the table and then index their place in the table when setting them after retrieving the data. You should also implement ways of preventing data loss in case of failure of getting/setting data as well.