How to datastore folder of strings and values inside the strings

so im a little stuck on finding a simplistic way of saving a ton of values, all im trying to do is save the values inside each player(which in this case is the C,HB,LT etc…)

serverscriptservice my current script that doesn’t work, no errors though, it only saves the first wave of string values not the ones inside also.

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local Saver = DataStoreService:GetDataStore("FootballPlayers1")

Players.PlayerAdded:Connect(function(player)
	local Data = nil
	local success, errormessage = pcall(function()
		Data = Saver:GetAsync(tostring(player.UserId))
	end)

	if success then
		if Data then
			for i, v in pairs(Data) do 
				player:WaitForChild("TeamPlayers"):WaitForChild(i).Value = v
			end
		end
	else
		error(errormessage)
	end
end)

local function Save(player)
	local SavedData = {}
	for _, v in pairs(player.TeamPlayers:GetChildren()) do
		SavedData[v.Name] = v.Value
	end

	local success, errormessage = pcall(function()
		Saver:SetAsync(tostring(player.UserId), SavedData)
	end)
	if not success then
		error(errormessage)
	end
end

Players.PlayerRemoving:Connect(Save)

game:BindToClose(function()
	for _, v in pairs(Players:GetPlayers()) do
		Save(v)
	end
end)

Screenshot 2025-01-16 211154

trying to save all those values above.

1 Like

Here is one way … You create an array {} and fill it with the values.
Then you reverse that on loading. No way this script will be 100% right, this takes testing.
Consider it a rough draft, more of a how to set this up…

local DataStoreService = game:GetService("DataStoreService")
local playerDataStore = DataStoreService:GetDataStore("PlayerData")


local function savePlayerData(player)
	local data = {}
	for _, teamFolder in pairs(player.TwixsDev.TeamPlayers:GetChildren()) do
		local teamData = {}
		for _, valueObject in pairs(teamFolder:GetChildren()) do
			teamData[valueObject.Name] = valueObject.Value
		end
		data[teamFolder.Name] = teamData
	end
	
	playerDataStore:SetAsync(player.UserId, data)
end

local function loadPlayerData(player)
	local data = playerDataStore:GetAsync(player.UserId)
	if data then
		
		for teamName, teamData in pairs(data) do
			local teamFolder = Instance.new("Folder", player.TwixsDev.TeamPlayers)
			teamFolder.Name = teamName
			for valueName, value in pairs(teamData) do
				local valueObject = Instance.new("StringValue", teamFolder)
				valueObject.Name = valueName
				valueObject.Value = value
			end
		end
	end
end

If may also want to use JSON with this.

local DataStoreService = game:GetService("DataStoreService")
local HttpService = game:GetService("HttpService")
local playerDataStore = DataStoreService:GetDataStore("PlayerData")

local function savePlayerData(player)
	local data = {}
	for _, teamFolder in pairs(player.TwixsDev.TeamPlayers:GetChildren()) do
		local teamData = {}
		for _, valueObject in pairs(teamFolder:GetChildren()) do
			teamData[valueObject.Name] = valueObject.Value
		end
		data[teamFolder.Name] = teamData
	end
	local jsonData = HttpService:JSONEncode(data)
	playerDataStore:SetAsync(player.UserId, jsonData)
end

local function loadPlayerData(player)
	local jsonData = playerDataStore:GetAsync(player.UserId)
	if jsonData then
		local data = HttpService:JSONDecode(jsonData)
		for teamName, teamData in pairs(data) do
			local teamFolder = Instance.new("Folder", player.TwixsDev.TeamPlayers)
			teamFolder.Name = teamName
			for valueName, value in pairs(teamData) do
				local valueObject = Instance.new("StringValue", teamFolder)
				valueObject.Name = valueName
				valueObject.Value = value
			end
		end
	end
end
1 Like

I don’t quite understand your code here, and in which way this will be implemented referring to my values.

I’m sure it is not all working … it’s just showing how to do it. Create this without the datastore at first.
You’re creating an Array/Table … filling it with your values in savePlayerData()
Then reversing that in loadPlayerData()

It’s because your for loop is only iterating through the direct children on the TeamPlayers folder and not every descendant, this causes it to only save the data of the string values from the immediate children and not all the other nested string values

Problem - Line 24

for _, v in pairs(player.TeamPlayers:GetChildren()) do

Solution

for _, v in pairs(player.TeamPlayers:GetDescendants()) do

Ah, so after I did this and changed the value to see if it saved, now when it tries to load my data I receive this error now.


this is a new error after i used your fix, seem like it detects it’s there now, but how would I load the values in, the error is in line 14.

	player:WaitForChild("TeamPlayers"):WaitForChild(i).Value = v

That’s because in your load function when you load the data for the individual player it will give you everything stored inside the folder and it doesn’t have a way to apply the data to the right slots, you’d need to make the function find the specific positions HB, RT, QB, and then apply the skincolor to the nested IntValues, I reccomend you take a different approach, add a Color3 value instead of intvalue and then name it the position_SkinColor, and then modify the value to be the color you want it to save as

image

And then in the save script do this:

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local Saver = DataStoreService:GetDataStore("FootballPlayers1")

Players.PlayerAdded:Connect(function(player)
	local Data = nil
	local success, errormessage = pcall(function()
		Data = Saver:GetAsync(tostring(player.UserId))
	end)

	if success then
		if Data then
			for dataKey, colorData in pairs(Data) do
				-- Expected key format: "Position_SkinColor" (e.g., "HB_SkinColor")
				local parts = string.split(dataKey, "_")
				if #parts == 2 then
					local positionName = parts[1]
					local propertyName = parts[2]

					local positionFolder = player:WaitForChild("TeamPlayers"):FindFirstChild(positionName)
					if positionFolder and propertyName == "SkinColor" then
						local colorValue = Instance.new("Color3Value")
						colorValue.Name = propertyName
						colorValue.Value = Color3.fromRGB(colorData.R, colorData.G, colorData.B)
						colorValue.Parent = positionFolder
					end
				end
			end
		end
	else
		warn("Error loading data for player:", player.Name, errormessage)
	end
end)

local function Save(player)
	local SavedData = {}
	local teamPlayers = player:FindFirstChild("TeamPlayers")
	if teamPlayers then
		for _, positionFolder in pairs(teamPlayers:GetChildren()) do
			if positionFolder:IsA("Folder") then
				local skinColorValue = positionFolder:FindFirstChild("SkinColor")
				if skinColorValue and skinColorValue:IsA("Color3Value") then
					local key = positionFolder.Name .. "_SkinColor"
					local color = skinColorValue.Value
					SavedData[key] = {R = math.floor(color.R * 255), G = math.floor(color.G * 255), B = math.floor(color.B * 255)}
				end
			end
		end
	end

	local success, errormessage = pcall(function()
		Saver:SetAsync(tostring(player.UserId), SavedData)
	end)
	if not success then
		warn("Error saving data for player:", player.Name, errormessage)
	end
end

Players.PlayerRemoving:Connect(Save)

game:BindToClose(function()
	for _, v in pairs(Players:GetPlayers()) do
		Save(v)
	end
end)

This avoids searching through nested children (saves on performance overhead) leading to the script performing it’s job faster, and also adds less clutter to the explorer.

Things like this are better built separately then added once perfected.
Just focus on building the array and reading it back first of all.

I did exactly what you said, the data doesn’t seem to save. Am i missing something? No errors in output.

to double check if anything is even loaded in i added a print below 21, i believe it isn’t receiving or loading the data.

local positionFolder = player:WaitForChild("TeamPlayers"):FindFirstChild(positionName)
					if positionFolder and propertyName == "SkinColor" then
						print("is color") 

it is not printing.
including lines 43-44

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local Saver = DataStoreService:GetDataStore("FootballPlayers1")

Players.PlayerAdded:Connect(function(player)
	print("Player added:", player.Name)
	local Data = nil
	local success, errormessage = pcall(function()
		Data = Saver:GetAsync(tostring(player.UserId))
	end)

	if success then
		print("Data loaded successfully for player:", player.Name)
		if Data then
			print("Loaded data:", Data)
			for dataKey, colorData in pairs(Data) do
				print("Processing dataKey:", dataKey, "with colorData:", colorData)
				-- Expected key format: "Position_SkinColor" (e.g., "HB_SkinColor")
				local parts = string.split(dataKey, "_")
				if #parts == 2 then
					local positionName = parts[1]
					local propertyName = parts[2]
					print("Extracted positionName:", positionName, "and propertyName:", propertyName)

					local positionFolder = player:WaitForChild("TeamPlayers"):FindFirstChild(positionName)
					if positionFolder then
						print("Found positionFolder:", positionFolder.Name)
						if propertyName == "SkinColor" then
							local colorValue = Instance.new("Color3Value")
							colorValue.Name = propertyName
							colorValue.Value = Color3.fromRGB(colorData.R, colorData.G, colorData.B)
							print("Setting SkinColor for", positionName, "to", colorValue.Value)
							colorValue.Parent = positionFolder
						end
					else
						print("Position folder not found:", positionName)
					end
				end
			end
		else
			print("No data found for player:", player.Name)
		end
	else
		warn("Error loading data for player:", player.Name, errormessage)
	end
end)

local function Save(player)
	print("Saving data for player:", player.Name)
	local SavedData = {}
	local teamPlayers = player:FindFirstChild("TeamPlayers")
	if teamPlayers then
		for _, positionFolder in pairs(teamPlayers:GetChildren()) do
			if positionFolder:IsA("Folder") then
				local skinColorValue = positionFolder:FindFirstChild("SkinColor")
				if skinColorValue and skinColorValue:IsA("Color3Value") then
					local key = positionFolder.Name .. "_SkinColor"
					local color = skinColorValue.Value
					SavedData[key] = {R = math.floor(color.R * 255), G = math.floor(color.G * 255), B = math.floor(color.B * 255)}
					print("Saving color for", positionFolder.Name, ":", SavedData[key])
				end
			end
		end
	end
	print("Data to be saved:", SavedData)

	local success, errormessage = pcall(function()
		Saver:SetAsync(tostring(player.UserId), SavedData)
	end)
	if not success then
		warn("Error saving data for player:", player.Name, errormessage)
	else
		print("Data saved successfully for player:", player.Name)
	end
end

Players.PlayerRemoving:Connect(Save)

game:BindToClose(function()
	print("Game is closing, saving data for all players.")
	for _, v in pairs(Players:GetPlayers()) do
		Save(v)
	end
end)

I asked chatgpt to add debug print statements, run this and see if it’s still working, i dont think it changed the logic but it might have, this will help me figure out where the problem lies though

Also send a video / the output when you run this, so im able to actually see what it’s doing wrong

no luck