Saving Folders Using DataStores

Hey there! How would I go about saving folders using datastores? I’ve tried doing it multiple times but failed. I would appreciate if anyone could help

2 Likes

You cannot save instances using datastore. You would have to save the properties of the instance and then load it in.

11 Likes

For instance (also in addition to @iNoobe_yt 's post), if you have Value Objects in the Folders, you can save their values, but not the actual object itself.You would have to create them on instance when the player rejoins, and add in the values.

1 Like

Ah Ok. Thanks for the help!

1 Like

I’ve created an example of what a datastore might look like using Value Objects’ Values as the to-be saved properties:

local DS = game:GetService("DataStoreService")
local PlrService = game:GetService("Players")


local function onPlayerRemoving(plr)
	
	wait()
	
	local Data = {}
	-- Saves values that currently exist.
	for _, ValuesToSave in pairs(plr:WaitForChild("leaderstats", math.huge):GetChildren()) do
		
		table.insert(Data, ValuesToSave.Value) -- will do this as listed in the leaderstats folder
		-- assuming ValuesToSave is a "Value" instance
	end
	
	if Data ~= nil then
		
		Storage:SetAsync(plr.UserId, Data) -- use plr.UserId as a "key"
		
	else
		
		print("No assets to save for " .. tostring(plr.Name) .. ".")
		
	end

end

PlrService.PlayerRemoving:Connect(onPlayerRemoving)

local function onPlayerAdded(plr)
	
	local SavedFiles = Storage:GetAsync(plr.UserId)

	if SavedFiles ~= nil then
		-- Retrieves Saved values from last time the player left the game.
		for _, LoadValues in pairs(SavedFiles) do
			
				-- now you've loaded the values, do whatever you want.
			end
			else
				
				print(tostring(LoadTools) .. " was not found in Library. Not loaded.")
			
			end
		
		end
		
	else
		
		print("No assets to load for " .. tostring(plr.Name) .. ".")
	
	end
	
	
end

PlrService.PlayerAdded:Connect(onPlayerAdded)

game:BindToClose(function()
	-- Just in case to give more time for saving Inventory...
	wait(10)
	
end)
7 Likes

Thanks for your help!

You can convert values to table in which folders are tables.

 someTable1:
  -> some_string_value: "asdasd"
  -> something_else: 5
 someTable2:
  ->  bool_value: true

The code would be something like this

function CompileData(folder, t)
	t = t or {}
	
	for i,v in pairs(folder:GetChildren()) do
		if v.ClassName == 'Folder' then
			t[v.Name] = CompileData(v)
		elseif v.ClassName == 'IntValue' or v.ClassName == 'NumberValue' or v.ClassName == 'StringValue' or v.ClassName == 'BoolValue' then
			t[v.Name] = v.Value
		elseif v.ClassName == 'Color3Value' then
			t[v.Name] = {
				__type = 'Color3',
				r = v.Value.r, g = v.Value.g, b = v.Value.g
			};
		end
	end
	
	return t
end

In case you want to save values other than primitives, you’ll have to store them as table and have a way of recognizing tables which are actually objects (in this case, it’s Color3 and is recognized by __type)

Converting the table to folder would be similar to this, but instead of checking ClassName, you should check which type is the value. e.g. type(123) ==> number and create values accordingly.

As for other values (non-primitives), you should check whether they have __type (in this case) and if they do, create value according to it. If it doesn’t have __type, it’s probably a folder.

8 Likes