I want to save a table of values. I heard that you need to use JSON format.
What is the issue?
It’s only printing to “Made it here 3” (I had others of course that’s why It’s at 3)
Here is the full code:
local dataStoreService = game:GetService("DataStoreService")
local dataStore = dataStoreService:GetDataStore("leaderstats")
local httpService = game:GetService("HttpService")
game.Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local armor = Instance.new("IntValue")
armor.Name = "Armor"
armor.Parent = leaderstats
local cash = Instance.new("IntValue")
cash.Name = "Cash"
cash.Parent = leaderstats
local dataLoaded = Instance.new("BoolValue")
dataLoaded.Name = "DataLoaded"
dataLoaded.Parent = player
local success, data = pcall(function()
return dataStore:GetAsync(player.UserId)
end)
if success then
print("Successfully got data for",player)
dataLoaded.Value = true
if data then
local dataDecoded = httpService:JSONDecode(data)
armor.Value = dataDecoded["Armor"]
cash.Value = dataDecoded["Cash"]
else
armor.Value = 0
cash.Value = 0
end
else
print("Failed to get data for",player,data)
dataLoaded.Value = false
player:Kick("Rejoin please")
end
end)
game.Players.PlayerRemoving:Connect(function(player)
if player.DataLoaded.Value == true then
local data = {
["Cash"] = player.leaderstats.Cash.Value,
["Armor"] = player.leaderstats.Armor.Value
}
local dataEncoded = httpService:JSONEncode(data)
local success, message = pcall(function()
print("Made it here 3")
dataStore:SetAsync(player.UserId, dataEncoded)
print("Made it here 4")
end)
if success then print("data saved for",player) else print("data did not save for",player,message) end
end
end)
What Solutions Have I Tried so far?
I’ve tried many solutions. From my own solutions to related dev forum threads. Too many to list
You don’t need to use JSON format. SetAsync encodes the value sent to JSON already. Pass it a Lua table. Remove line 50 and you’ll have no issues saving that data table defined at 46-49. You do however, need to use JSON supported values (numbers, strings, tables). In your case, you’re fine, but don’t try to save a Vector3 or Color3 value, etc (userdata not supported by backend JSON encoding)
If you’re only calling this on PlayerRemoving and expecting it to finish before the studio session ends, then that is your problem. PlayerRemoving will (sometimes) fire when you press Stop in studio, but unlike BindToClose, it will not yield. This means line 53 may not be running at all before the datamodel is closed. Below is a setup you could use that supports both PlayerRemoving and BindToClose
local function Save(player)
if player.DataLoaded.Value == true then
local data = {
["Cash"] = player.leaderstats.Cash.Value,
["Armor"] = player.leaderstats.Armor.Value
}
--local dataEncoded = httpService:JSONEncode(data) -- commented out as it's not needed.
local success, message = pcall(function()
print("Made it here 3")
dataStore:SetAsync(player.UserId, data)
print("Made it here 4")
end)
if success then
print("data saved for",player)
else
print("data did not save for",player,message)
end
end
end
if not game:GetService("RunService"):IsStudio() then -- only call this outside of studio (when used in conjunction with a BindToClose save). If you remove this if statement both PlayerRemoving and BindToClose may fire the save when you press Stop, causing you to hit the write limit.
game.Players.PlayerRemoving:Connect(Save)
end
game:BindToClose(function()
for _,player in pairs(game.Players:GetPlayers()) do
local s, e = pcall(Save, player) --pcall incase of error, we want to continue to loop other players
end
end
If you remove that line, you will notice that studio yields for longer than ideal. This is because, when used with a BindToClose save call, it causes SetAsync to be throttled because you have a chance to be calling two saves at the exact same time. SetAsync only allows 1 call per key every 6 seconds