Datastores not working correctly

When i go to my second place, for example, though it doesn’t load my saved Part 1 values.
Here’s the code for the second place:

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local playerDataStore = DataStoreService:GetDataStore("playerData")

local defaultData = {
	leaderstats = {
		["Deaths II"] = 0,
		["Escapes II"] = 0,
	},

	storedData = {
		["Deaths I"] = 0,
		["Escapes I"] = 0,
		["Deaths III"] = 0,
		["Escapes III"] = 0
	}
}

local leaderstatsName = game.PlaceId == myreal2ndplaceidishere and "leaderstats" or "folder"

local function SaveData(player, data)
	local success, errorMessage = pcall(function()
		playerDataStore:SetAsync(player.UserId, data)
	end)

	if not success then
		warn(errorMessage)
	end
end

local function OnPlayerRemoving(player)
	local data = defaultData

	for folderName, folderValues in defaultData do
		local folder = player[folderName == "leaderstats" and leaderstatsName or folderName]

		for valueName, _ in folderValues do
			data[folderName][valueName] = folder[valueName].Value
		end
	end

	SaveData(player, data)
end

Players.PlayerAdded:Connect(function(player)
	local playerData = playerDataStore:GetAsync(player.UserId) or defaultData

	for folderName, folderValues in defaultData do
		local folder = Instance.new("Folder")
		folder.Name = folderName == "leaderstats" and leaderstatsName or folderName

		for valueName, _ in folderValues do
			local intValue = Instance.new("IntValue")
			intValue.Name = valueName
			intValue.Value = playerData[folderName][valueName]
			intValue.Parent = folder
		end

		folder.Parent = player
	end
end)

Players.PlayerRemoving:Connect(OnPlayerRemoving)

game:BindToClose(function()
	for i, player in Players:GetPlayers() do
		task.spawn(OnPlayerRemoving, player)
	end
end)

Yeah, is that not what you wanted the script to do?

If you want everything to load, use the original script here:

That is what i want, but when i check the storedData folder inside of the Player, where Deaths1, Escapes1, Deaths3, & Escapes3 should all be, they’re in the folder but their values are all at zero, so they didn’t save from place 1 or place 3. I’m trying to get all of the data to transfer to the other places because in my Lobby place i have leaderboards for each of the different values.

Oh, I just realized you did it wrong. If you want the leaderstats to only show the current world’s count, then we have to do something different.

Code:

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local playerDataStore = DataStoreService:GetDataStore("playerData")

local defaultData = {
	["Deaths I"] = 0,
	["Escapes I"] = 0,
	["Deaths II"] = 0,
	["Escapes II"] = 0,
	["Deaths III"] = 0,
	["Escapes III"] = 0
}

local leaderstatValues = {"Death I", "Escapes I"} -- Change this depending on level

local function SaveData(player, data)
	local success, errorMessage = pcall(function()
		playerDataStore:SetAsync(player.UserId, data)
	end)

	if not success then
		warn(errorMessage)
	end
end

local function OnPlayerRemoving(player)
	local leaderstats = player.leaderstats
	local storedData = player.storedData
	
	local data = {}

	for valueName, _ in defaultData do
		data[valueName] = table.find(leaderstatValues, valueName) and leaderstats[valueName].Value or storedData[valueName].Value
	end

	SaveData(player, data)
end

Players.PlayerAdded:Connect(function(player)
	local playerData = playerDataStore:GetAsync(player.UserId) or defaultData
	
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	
	local storedData = Instance.new("Folder")
	storedData.Name = "storedData"
	
	for valueName, _ in defaultData do
		local intValue = Instance.new("IntValue")
		intValue.Name = valueName
		intValue.Value = playerData[valueName]
		intValue.Parent = table.find(leaderstatValues, valueName) and leaderstats or storedData
	end
	
	leaderstats.Parent = player
	storedData.Parent = player
end)

Players.PlayerRemoving:Connect(OnPlayerRemoving)

game:BindToClose(function()
	for i, player in Players:GetPlayers() do
		task.spawn(OnPlayerRemoving, player)
	end
end)

You will have to reset your data again.

Do i need to reset everybody’s data as well? because there are a couple of other people that have tested my game out and they have data. Is there a way to reset all data? if that’s what i need to do?

You can use this in your command bar:

local DSS = game:GetService("DataStoreService")
local DataStore = DSS:GetDataStore("playerData")
local KeysPages = DataStore:ListKeysAsync()
		
while true do
	local CurrentKeysPage = KeysPages:GetCurrentPage()
			
	for j, Key in pairs(CurrentKeysPage) do
		DataStore:RemoveAsync(Key.KeyName)
	end
			
	if KeysPages.IsFinished then break end
			
	KeysPages:AdvanceToNextPageAsync()
end

If you want me to implement a way that preserves their data, tell me. There will be a performance cost though.

The data still isn’t saving or transferring.
Code:

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local playerDataStore = DataStoreService:GetDataStore("playerData")

local defaultData = {
	["Deaths I"] = 0,
	["Escapes I"] = 0,
	["Deaths II"] = 0,
	["Escapes II"] = 0,
	["Deaths III"] = 0,
	["Escapes III"] = 0
}

local leaderstatValues = {"Deaths I", "Escapes I"} -- Change this depending on level

local function SaveData(player, data)
	local success, errorMessage = pcall(function()
		playerDataStore:SetAsync(player.UserId, data)
	end)

	if not success then
		warn(errorMessage)
	end
end

local function OnPlayerRemoving(player)
	local leaderstats = player.leaderstats
	local storedData = player.storedData

	local data = {}

	for valueName, _ in defaultData do
		data[valueName] = table.find(leaderstatValues, valueName) and leaderstats[valueName] or storedData[valueName]
	end

	SaveData(player, data)
end

Players.PlayerAdded:Connect(function(player)
	local playerData = playerDataStore:GetAsync(player.UserId) or defaultData

	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"

	local storedData = Instance.new("Folder")
	storedData.Name = "storedData"

	for valueName, _ in defaultData do
		local intValue = Instance.new("IntValue")
		intValue.Name = valueName
		intValue.Value = playerData[valueName]
		intValue.Parent = table.find(leaderstatValues, valueName) and leaderstats or storedData
	end

	leaderstats.Parent = player
	storedData.Parent = player
end)

Players.PlayerRemoving:Connect(OnPlayerRemoving)

game:BindToClose(function()
	for i, player in Players:GetPlayers() do
		task.spawn(OnPlayerRemoving, player)
	end
end)

You’re testing this ingame right? If so, does it save when you leave and rejoin for place one?

Yes, i tested it ingame. It doesn’t save when i leave and rejoin place one.

Are there any errors or warnings?

You only ran the command once right?

I ran the command for myself a couple of times on accident lol. And i ran the one that resets all datastores once.
Here’s what’s in the Output:

  • DataStoreService: CantStoreValue: Cannot store Dictionary in data store. Data stores can only accept valid UTF-8 characters. API: SetAsync, Data Store: playerData - Studio
  • Cannot store Dictionary in data store. Data stores can only accept valid UTF-8 characters. - Server - Leaderstats/Datastore:22

Oops, I made a typo. Check my edited code.

which code did you edit? i can’t tell lol

1 Like

i replace the code with that and its still not working. Wait… im testing in roblox studio right now and when i open up the player in the explorer there are two leaderstats folders in there, one of them has the saved values and the other has zero values.
Edit: i accidentally had another script that was creating a leaderstats folder and i forgot to delete it, so im gonna test in Roblox again quick.

IT WORKS FINALLY THANK YOU SO MUCH! especially for your quick responses!!!
Here’s the working code:

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local playerDataStore = DataStoreService:GetDataStore("playerData")

local defaultData = {
	["Deaths I"] = 0,
	["Escapes I"] = 0,
	["Deaths II"] = 0,
	["Escapes II"] = 0,
	["Deaths III"] = 0,
	["Escapes III"] = 0
}

local leaderstatValues = {"Deaths I", "Escapes I"}

local function SaveData(player, data)
	local success, errorMessage = pcall(function()
		playerDataStore:SetAsync(player.UserId, data)
	end)

	if not success then
		warn(errorMessage)
	end
end

local function OnPlayerRemoving(player)
	local leaderstats = player.leaderstats
	local storedData = player.storedData

	local data = {}

	for valueName, _ in defaultData do
		data[valueName] = table.find(leaderstatValues, valueName) and leaderstats[valueName].Value or storedData[valueName].Value
	end

	SaveData(player, data)
end

Players.PlayerAdded:Connect(function(player)
	local playerData = playerDataStore:GetAsync(player.UserId) or defaultData

	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"

	local storedData = Instance.new("Folder")
	storedData.Name = "storedData"

	for valueName, _ in defaultData do
		local intValue = Instance.new("IntValue")
		intValue.Name = valueName
		intValue.Value = playerData[valueName]
		intValue.Parent = table.find(leaderstatValues, valueName) and leaderstats or storedData
	end

	leaderstats.Parent = player
	storedData.Parent = player
end)

Players.PlayerRemoving:Connect(OnPlayerRemoving)

game:BindToClose(function()
	for i, player in Players:GetPlayers() do
		task.spawn(OnPlayerRemoving, player)
	end
end)
1 Like

No problem, I would appreciate the solution though.

If you have any questions, feel free to ask. Have a good day/night!

1 Like

Of course!! Thank you so much!

1 Like

I actually do have a quick question lol. Now that the Datastores work, i’m trying to refresh my physical Global Leaderboards so that they erase there old data. I especially want to do this because some of the names on the leaderboard say “Not Available” and i think that should be fixed with the new Datastore system.
Here’s what the code looks like for one part of the leaderboards: (they’re all the same exact with the different values for each of course)

local StatsName = "Deaths I"
local MaxItems = 100
local MinValueDisplay = 1
local MaxValueDisplay = 10e15
local UpdateEvery = math.random(15, 60)

local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard_" .. StatsName)
local SurfaceGui = script.Parent
local Sample = script.Sample
local List = SurfaceGui.Frame.List
local ItemsFrame = List.ListContent.Items

local function GetItems()
	local Data = DataStore:GetSortedAsync(false, MaxItems, MinValueDisplay, MaxValueDisplay)
	local TopPage = Data:GetCurrentPage()
	
	ItemsFrame.Nothing.Visible = #TopPage == 0 and true or false
	
	for i, v in ipairs(TopPage) do
		local UserId = v.key
		local Value = v.value
		local Username = "[Not Available]"
		local Color = Color3.fromRGB(38, 50, 56)
		
		local Success, Error = pcall(function()
		 	Username = game.Players:GetNameFromUserIdAsync(UserId)
		end)
		
		if i == 1 then
			Color = Color3.fromRGB(255, 215, 0)
		elseif i == 2 then
			Color = Color3.fromRGB(192, 192, 192)
		elseif i == 3 then
			Color = Color3.fromRGB(205, 127, 50)
		end
		
		local Item = Sample:Clone()
		Item.Name = Username
		Item.LayoutOrder = i
		Item.Values.Number.TextColor3 = Color
		Item.Values.Number.Text = i
		Item.Values.Username.Text = Username
		Item.Values.Value.Text = Value
		Item.Parent = ItemsFrame
	end
end

while true do
	for i, v in pairs(game.Players:GetPlayers()) do
		local Stats = v.storedData:WaitForChild(StatsName).Value
		if Stats then
			pcall(function()
				DataStore:UpdateAsync(v.UserId, function(Value)
					return tonumber(Stats)
				end)
			end)
		end
	end
	
	for i, v in pairs(ItemsFrame:GetChildren()) do
		if v:IsA("ImageLabel") then
			v:Destroy()
		end
	end
	
	GetItems()
	
	wait()
	SurfaceGui.Heading.Heading.Text = StatsName .. " Leaderboard"
	List.ListContent.GuideTopBar.Value.Text = StatsName
	List.CanvasSize = UDim2.new(0, 0, 0, ItemsFrame.UIListLayout.AbsoluteContentSize.Y + 35)
	wait(UpdateEvery)
end

Those not available names could be because of a Local Server test, since the players created there don’t exist. You can try to change the DataStoreKey and it should be fine.

Code:

local DataStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard1_" .. StatsName)

You can also add checks to not save userIds under 0.

1 Like