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
You cannot save instances using datastore. You would have to save the properties of the instance and then load it in.
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.
Ah Ok. Thanks for the help!
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)
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.