Save data system issue

I try to create save data system but the system doesn’t work well. Are there any solutions?

Problem: when player rejoin the server, player’s Win and BeyPoints value are reset 100BP.
Notes: there are no error message.

local DataStoreService = game:GetService("DataStoreService")
local RunService = game:GetService("RunService")
local database = DataStoreService:GetDataStore("data")
local sessionData = {}

function PlayerAdded(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	--Win
	local Win = Instance.new("IntValue")
	Win.Name = "Win"
	Win.Parent = leaderstats
	--Points
	local BeyPoints = Instance.new("IntValue")
	BeyPoints.Name = "BeyPoints"
	BeyPoints.Parent = leaderstats
	
	local success = nil
	local playerData = nil
	local attempt = 1
	
	repeat
		success, playerData=pcall(function()
			return database:GetAsync(player.UserId)
		end)
		attempt += 1
		if not success then
			warn(playerData)
			task.wait(3)
		end
	until success or attempt == 5
	
	if success then
		print("Connected to database")
		if not playerData then
			print("Assignig default data")
			playerData = {
				["Win"] = 0,
				["BeyPoints"] = 100
			}
		end
		sessionData[player.UserId] = playerData
	else
		warn("Unable to get data for", player.UserId)	
		player:Kick("Try to connect server again :-O")
	end
	
	Win.Value = sessionData[player.UserId].Win
	Win.Changed:Connect(function()
		sessionData[player.UserId].Win = Win.Value
	end)
	
	BeyPoints.Value = sessionData[player.UserId].BeyPoints
	BeyPoints.Changed:Connect(function()
		sessionData[player.UserId].BeyPoints = BeyPoints.Value
	end)
	
	leaderstats.Parent = player
	print(player, "is participating")
end

Players.PlayerAdded:Connect(PlayerAdded)



function PlayerLeaving(player)
	if sessionData[player.UserId] then
		local success = nil
		local errorMsg = nil
		local attempt = 1
		repeat
			success, errorMsg=pcall(function()
				database:SetAsync(player.UserId, sessionData[player.UserId])
			end)
			attempt += 1
			if not success then
				warn(errorMsg)
				task.wait(3)
			end
		until success or attempt == 5
		
		if success then
			print("Data saved for", player.Name)
		else
			warn("Unable t save for", player.Name)
		end
	end
	print(player, "is leaving")
end

Players.PlayerRemoving:Connect(PlayerLeaving)


function ServerShutdoen()
	if RunService:IsStudio() then
		return
	end
	print("Server shutting down")
	for i, player in ipairs(Players:GetPlayers()) do
		--task.spawn(function()
			PlayerLeaving(player)
		--end)
	end
end

game:BindToClose(ServerShutdoen)
2 Likes

Well, to start, the reason you may have no error messages is because you have a pcall wrapped around your data store’s GetAsync function:

If you remove the pcall (for now). See if there’s an error. I suspect that you don’t have that one setting enabled (forgot what it’s called for like the 20th time).

Think it was called “Enable API services for your game”.

1 Like

Thank you for replying!
I just removed pcall, but basically there was no error message.
However, it seems that PlayerLeaving function doesn’t work and success remain nil.

I can’t understand why this issue occur…

1 Like

If you are saving multiple values for each player you are probably trying to save a table, which you can not save in roblox datastores. To bypass this you have to convert the table into a JSON string when saving and when loading the JSON String you convert it into a table:

local httpService = game:GetService("HttpService")
local t = {1;2;"a"}

t = httpService:JSONEncode(t) -- Table to JSON
t = httpService:JSONDecode(t) -- JSON to Table
1 Like

Thank you for replying!
But, I’ve never heard that JSON String and I can’t understand how to put this system into my code completly.
So, if you have a time, would you tell me how to put JSON String into my code concretely ?:pray:

1 Like
local DataStoreService = game:GetService("DataStoreService")
local RunService = game:GetService("RunService")
local database = DataStoreService:GetDataStore("data")
local httpService = game:GetService("HttpService")

local sessionData = {}

function PlayerAdded(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	--Win
	local Win = Instance.new("IntValue")
	Win.Name = "Win"
	Win.Parent = leaderstats
	--Points
	local BeyPoints = Instance.new("IntValue")
	BeyPoints.Name = "BeyPoints"
	BeyPoints.Parent = leaderstats
	
	local success = nil
	local playerData = nil
	local attempt = 1
	
	repeat
		success, playerData=pcall(function()
			return database:GetAsync(player.UserId)
		end)
		attempt += 1
		if not success then
			warn(playerData)
			task.wait(3)
		end
	until success or attempt == 5
	
	if success then
		print("Connected to database")
		if not playerData then
			print("Assignig default data")
			playerData = {
				["Win"] = 0,
				["BeyPoints"] = 100
			}
                else
                        playerData = httpService:JSONDecode(playerData)
                         sessionData[player.UserId] = playerData
		end
		
	else
		warn("Unable to get data for", player.UserId)	
		player:Kick("Try to connect server again :-O")
	end
	
	Win.Value = sessionData[player.UserId].Win
	Win.Changed:Connect(function()
		sessionData[player.UserId].Win = Win.Value
	end)
	
	BeyPoints.Value = sessionData[player.UserId].BeyPoints
	BeyPoints.Changed:Connect(function()
		sessionData[player.UserId].BeyPoints = BeyPoints.Value
	end)
	
	leaderstats.Parent = player
	print(player, "is participating")
end

Players.PlayerAdded:Connect(PlayerAdded)



function PlayerLeaving(player)
	if sessionData[player.UserId] then
		local success = nil
		local errorMsg = nil
		local attempt = 1
           
		repeat
			success, errorMsg=pcall(function()
				database:SetAsync(player.UserId, httpService:JSONEncode(sessionData[player.UserId]))
			end)
			attempt += 1
			if not success then
				warn(errorMsg)
				task.wait(3)
			end
		until success or attempt == 5
		
		if success then
			print("Data saved for", player.Name)
		else
			warn("Unable t save for", player.Name)
		end
	end
	print(player, "is leaving")
end

Players.PlayerRemoving:Connect(PlayerLeaving)


function ServerShutdoen()
	if RunService:IsStudio() then
		return
	end
	print("Server shutting down")
	for i, player in ipairs(Players:GetPlayers()) do
		--task.spawn(function()
			PlayerLeaving(player)
		--end)
	end
end

game:BindToClose(ServerShutdoen)
1 Like

You don’t have to use JSON Encoding/Decoding for this, you just have to make sure you are referencing your tables correctly.

			playerData = {
				["Win"] = 0,
				["BeyPoints"] = 100
			}
print(playerData.Win)
-- nil
print(playerData["Win"])
-- 0

Try replacing this whole block and see what happens.

	Win.Value = sessionData[player.UserId]["Win"]
	--Win.Value = sessionData[player.UserId].Win
	Win.Changed:Connect(function()
		sessionData[player.UserId]["Win"] = Win.Value
		--sessionData[player.UserId].Win = Win.Value
	end)

	BeyPoints.Value = sessionData[player.UserId]["BeyPoints"]
	--BeyPoints.Value = sessionData[player.UserId].BeyPoints
	BeyPoints.Changed:Connect(function()		
		sessionData[player.UserId]["BeyPoints"] = BeyPoints.Value
		--sessionData[player.UserId].BeyPoints = BeyPoints.Value
	end)
1 Like

Thank you for replying and this cord work well!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.