How can I save different kind of values parented to a folder?

Hello fellow developers!

I’ve encounter an issue that is pretty disturbing; I have no idea how I can save different kinds of values (BoolValue, StringValue, IntValue,…) that are parented to a folder. That folder is in the ServerStorage and once a player joins, it goes into that player. I’ve been reading lots of forums about my problem, but none of them were a success. I have a lack of knowledge about data storage and I would really like learning more about it. Any help is appreciated, thanks in advance!

Here are some pictures of my hierarchy:

(the folder that I want to be saved is the one called “SavedValues”)

This is a screenshot of the ServerStorage before playing
Capture d’écran 2022-07-22 à 15.49.38

This is a screenshot of the player’s children after the player starts playing.The folder goes into the player and is no longer in the ServerStorage!
Capture d’écran 2022-07-22 à 15.52.16

Some of the values inside the folder are BoolValues, other are IntValues, …

Thanks again!

You might want to try cloning the folder using ServerStorage.EggHatchingData.SavedValues:Clone(), then set the parent of the clone to the player, like so:

local savedValues = ServerStorage.EggHatchingData.SavedValues:Clone()
savedValues.Parent = player

I hope this helps

1 Like

But is there any way to make the values inside of that folder save?

You have to manually save each value to datastore, using a for loop as so:

for _, value in ipairs(player.SavedValues:GetChildren()) do
    saveValueToDatastore(value.Name, value.Value) -- this function saves the value to the datastore, you will need to write this function yourself
end

yeah that is pretty disturbing. I would recommend you to already clone the folder to the player when he joins. You have to create the Values and Folders by script or just parent the Folder to the player with following code:

game.Players.PlayerAdded:Connect(function(player)
	local Clone = game.ServerStorage.EggHatchingData:Clone()
	Clone.Parent = player
end)

To save this value you have to add a datastore. Since this takes some time idk:
here is an example script:

--Vars and Services
local DataStore = game:GetService("DataStoreService"):GetDataStore("MainDatastore")

--Functions
function formatData(player)

	local data = {}

	local YourFolder = player:WaitForChild("leaderstats")
	local steps = {}

	for i,piece in pairs(YourFolder:GetChildren()) do
		table.insert(steps, piece.Value)
	end

	table.insert(data, steps)
	return data
end

function saveData(player)
	local Key = "Player_"..player.UserId
	local stuffToSave = formatData(player)

	local succes, err = pcall(function()

		if stuffToSave then
			DataStore:SetAsync(Key, stuffToSave)
		end

	end)

	if err then
		warn('WARNING: COULD NOT SAVE PLAYER DATA: '..err)
	end
end

function loadData(player)
	--CREATING FOLDERS
	local Key = "Player_"..player.UserId

	local Board = Instance.new("Folder")
	Board.Name = "leaderstats"
	Board.Parent = player
	local Traveled = Instance.new("IntValue", Board)
	Traveled.Name = "Studs"
	------------------------------------------------------------

	--GETTING PLAYER DATA
	local sucess, err = pcall(function()
		local data = DataStore:GetAsync(Key)
		if data then
			if data[1] then
				Traveled.Value = data[1][1] -- The first section of the folder, first value: FreeSkips
			else
				Traveled.Value = 0
			end
		else  -- if data doesn't exist         
			Traveled.Value = 0
		end
	end)

	if err then
		warn('WARNING: COULD NOT LOAD PLAYER DATA: '..err)
	end

end

function onServerShutdown()
	if game:GetService("RunService"):IsStudio() then
		wait(2)
	else
		for _, player in pairs(game.Players:GetPlayers()) do
			local finished = Instance.new("BindableEvent")

			saveData(player) --It's easier to use the previous saveData function on each player than it is to write new code

			finished.Event:Wait()
		end		
	end
end


--Binding Events
game:BindToClose(onServerShutdown)
game.Players.PlayerAdded:Connect(loadData)
game.Players.PlayerRemoving:Connect(saveData)

This script saves everything of one specific folder (here called leaderstats). Since your Folder has even more Folder inside it you have to create multiple table for each folder and then save these tables again into 1 WHOLE Table. Then for the load data function you have to define your folders (in this example the Folder is being created by script, you have to locate your folder (:waitforchild(“folder”)), since its not being created by this script. AND THEN, you have to (for every value) what value it should have if there is no data yet (in the script its the load data function)

local sucess, err = pcall(function()
		local data = DataStore:GetAsync(Key)
		if data then
			if data[1] then
				Traveled.Value = data[1][1] -- The first section of the folder, first value: FreeSkips
			else
				Traveled.Value = 0
			end
		else  -- if data doesn't exist         
			Traveled.Value = 0
		end
	end)

in this example the value (traveled) gets reset to 0 if no data is existing, else it gets the data of the first folder. Since you parent your Folder you can skip this. You just have to add the Starter Values for the Values by simply changing them all to the Value you want to have if no data exists yet. IF data is existing you have to define which data you want from the table. In the example there is only one folder created and only 1 value is in the folder, so: data[1][1] – The first section of the folder, first value
But if you created (for example) another folder called “a” and a Value inside it, called “b” AND you want the Value of the Value “b” you have to make it like this: data[2][1], since its the second folder being loaded or saved. Same for the values in the specific folders. Second Value in a Folder goes like this:
data[2][2]

You see it complicated and i tried my best (with my bad english skills) to explain to you, how to save data with a datastore. Hope this helps a bit!

1 Like

Also this does not matter, since every child of the defined folder gets saved. Important is that you already make the Values to the Starter Value. So if no data is existing the game just uses this value to continue. For example you want a start amount of 100 coins → change the Value of the CollectedCoin Value to 100. Just saying that because the Folder is not being created by the script.

1 Like

No problem. You can mark it as the solution if you want :grin:

1 Like

I surely will mark it as a solution :wink: ! Thanks again

1 Like