DataStore Problem/Data Loss

Thanks for pointing that out i fixed the post.

I left out the local for plr.

game:BindToClose(function()
local plr = game.Players.LocalPlayer.Name
saveData(plr)
end)

A better option would be too do

game:BindToClose(function()
	for _,v in pairs(game.Players:GetChildren()) do
		saveData(v.Name) -- v is the player name
	end
end)

In this example, v would not be the player name, v would be the player instance. You’d need to say v.Name to get the actual player name.

I made a tutorial on YouTube using this code. It seems to work for me (this version is untested).

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local dataStore = DataStoreService:GetDataStore("name_here")

local dataLoaded = false
local tries = 3

local function Set(plr)
	if dataLoaded then
		local key = "key#-" .. plr.UserId
		
		local data = {
			["currency1"] = plr.leaderstats.name.Value,
			["currency2"] = plr.leaderstats.name2.Value
		}
		
		local success, err
		local count = 0
		
		repeat
			success, err = pcall(function()
				dataStore:SetAsync(key, data)
			end)
			
			count = count + 1
			
			wait(0.5)
		until count >= tries or success
		
		if not success then
			warn("Failed to serialize data. Error code: " .. tostring(err))
			
			return
		end
	end
end

local function Get(plr)
	local key = "key#-" .. plr.UserId
	
	local serialized
	local success, err
	
	local count = 0
	
	repeat
		success, err = pcall(function()
			serialized = dataStore:GetAsync(key)
		end)
		
		count = count + 1
		
		wait(0.5)
	until count >= tries or success
	
	if not success then
		warn("Failed to read data. Error code: " .. tostring(err))
		
		return
	end
	
	if serialized then
		return serialized
	else
		local starterStats = {
			["currency1"] = 10,
			["currency2"] = 20
		}
		
		return starterStats
	end
end

local function CreateStats(plr)
	local stats = Instance.new("Folder")
	stats.Name = "leaderstats"
	stats.Parent = plr
	
	local data = Get(plr)
	
	local currency1 = Instance.new("IntValue")
	currency1.Name = "name"
	currency1.Parent = stats
	
	local currency2 = Instance.new("IntValue")
	currency2.Name = "name2"
	currency2.Parent = stats
	
	currency1.Value = data.currency1
	currency2.Value = data.currency2
	
	dataLoaded = true
	Set(plr)
end

game:BindToClose(function()
	for _, v in pairs(game.Players:GetChildren()) do
		Set(v.Name) -- v.Name is the player name
	end
end)

Players.PlayerAdded:Connect(CreateStats)
Players.PlayerRemoving:Connect(Set)

You forgot to add a BindToClose function. This needs to be added just incase of server shutdown data won’t be lost. It is better to use UpdateAsync than SetAsync.

game:BindToClose(function()
	for _,v in pairs(game.Players:GetChildren()) do
		Set(v.Name) -- v.Name is the player name
	end
end)
2 Likes

Really, the only solution is to change to a new system, unfortunately you will have to rewrite everything.

UpdateASync() caused more problems somehow. (More reports coming about data loss now)

There’s a lot of data here, and people bought items/upgrades with real money. So I can’t rewrite everything, data scheme must remain the same.

It would make it easier if you provide a screenshot of the PlayerSave tell us if its Bool,Number,String values. The Player that reports data loss is it just certain data(if so which value) or is the whole safe getting wiped?

All data getting wiped somehow.

(I know the screenshot has more data than script but, I just added part of the script here)

There is A lot of Data in that folder that needs to be saved. If you go over the Data store limit of 260,000 it wont save everything. To check the amount of Data you are saving you can use this script.

	local j = game:GetService("HttpService"):JSONEncode(Saving) -- Saving is the Table with the Data
		print("JSON Encode: " .. j) -- Prints out the encoded data
		print("JSON length: " .. #j) -- tells you how much data is in the table

I wrote a quick DataStore script that will loop through the table when a player enters and load the data. It also loops through the folder saving each value to the table named “Saving”. I have tested it with your old script and everything loaded fine. Just be sure to do more testing with it. Also if your game has stuff you can buy with robux I recommend saving when someone buys something.

local DataStore = game:GetService("DataStoreService"):GetDataStore("Data")


function loadData(plr)
	local Folder = game.ReplicatedStorage:WaitForChild(plr.Name)
	local key = plr.UserId
	
	local success, message = pcall(function()
		local Data = DataStore:GetAsync(key)
		
		if Data ~= nil then
			for i, v in pairs(Data) do
				for _,k in pairs(game.ReplicatedStorage[plr.Name]:GetChildren()) do
					if i == k.Name then
						k.Value = v
					end
				end
			end
		else
			print("New Player  " .. plr.Name)
		end
	end)
	if success then
		print("Player Data Loaded for " .. plr.Name)
	end
	if message then 
		print("Player Data NOT loaded for " .. plr.Name .. " Error: ".. message)
	end
end

function saveData(plr)
	local Folder = game.ReplicatedStorage:WaitForChild(plr.Name):GetChildren()
	local key = plr.UserId
	local Saving = {}
	
	for _,v in pairs(game.ReplicatedStorage[plr.Name]:GetChildren()) do
		Saving[v.Name] = v.Value
	end
	
	local j = game:GetService("HttpService"):JSONEncode(Saving)
		print("JSON Encode: " .. j)
		print("JSON length: " .. #j)
	
	local success, message = pcall(function()	
	DataStore:SetAsync(key, Saving)
	end)
	if success then 
		print("Data Successfully saved for ".. plr.Name)
	else
		print(message)
	end
end

game.Players.PlayerAdded:Connect(function(plr)
	if game.ReplicatedStorage:FindFirstChild(plr.Name) ~= nil then
		game.ReplicatedStorage:FindFirstChild(plr.Name):Destroy()
	end
	
	local Folder = game.ReplicatedStorage.PlayerSave:Clone()
	Folder.Parent = game.ReplicatedStorage
	Folder.Name = plr.Name
	game.ReplicatedStorage:WaitForChild(plr.Name)
	
	loadData(plr)
end)

game.Players.PlayerRemoving:Connect(function(plr)
	saveData(plr)
end)

game:BindToClose(function()
	if game:GetService("RunService"):IsStudio() then
		return
	end
	
	for _, Name in pairs(game.Players:GetChildren()) do
		saveData(Name)
	end
end)

Here is the Script. Be sure to read through it before using and test it in studios before you publish. You can also use Crazyman32 DataStore Editor in studios.

1 Like

Thank you so much! I’ll let you know the result after testing. (Still testing)

Thanks for the code! Problem is still happening but more rare. I’m marking it as a solution for now.