Multi-Saving DataStore

Currently, my DataStore is capable of saving // restoring all values within a given folder - However, the format only works if the Values are direct children of the Folder / Configuration being changed as such:

image

Below is what I wish to achieve:
image

I wish to maintain the over-all Save function in which it is capable of saving everything rather than looking for a labelled specific value. I have included the coding.

SaveData
	local success, Data = pcall(function()
		return DataStoreService:SetAsync(Player.UserId, saveToDictionary(Player["PlayerData"]))
	end)
	if success then end
end

function saveToDictionary(object)
	if not object:IsA("Configuration") then
		if (object:IsA("Color3Value")) then
			return { "Color3", tostring(object.Value) }
		end
		return object.Value
	else
		local newTable = {}
		for i,v in pairs(object:GetChildren()) do
			newTable[v.Name] = saveToDictionary(v)
		end
		return newTable
	end
LoadData
function materializeDictionary(input)
	if typeof(input) == "table" then
		if (input[1] == "Color3") then
			local newColor3Value = Instance.new("Color3Value")
			newColor3Value.Value = Color3.new(unpack(input[2]:split(", ")))
			return newColor3Value
		end
	
	local newConfig = Instance.new("Configuration")
	for i,v in pairs(input) do
		local newObject = materializeDictionary(v)
		newObject.Name = i
		newObject.Parent = newConfig
		end
	return newConfig
	
	elseif typeof(input) == "number" then
		local newIntValue = Instance.new("NumberValue")
		newIntValue.Value = input
		return newIntValue
	elseif typeof(input) == "string" then
		local newStringValue = Instance.new("StringValue")
		newStringValue.Value = input
		return newStringValue
	elseif typeof(input) == "boolean" then
		local newBoolValue = Instance.new("BoolValue")
		newBoolValue.Value = input
		return newBoolValue
	end
end

Thank you!

1 Like

Well dude.
Your save function only looks at the children of objects with the configuration classname. HairType and OutfitType aren’t configuration objects so the save function never looks at their children.

Try this
userdata_to_table = function (userdata)
	if not (userdata and type(userdata)=='userdata') then
		return nil
	end
	
	local entry = {}
	
	entry.Class=userdata.ClassName
	if (userdata:IsA('ValueBase')) then
		entry.Value=tostring(userdata.Value)
	end
	
	entry.children = {}
	for _, obj in pairs(userdata:GetChildren()) do
		local child = userdata_to_table(obj)
		entry.children[obj.Name]=child
	end
	
	return entry
end


table_to_userdata = function(tab)
	if not (tab and type(tab)=='table' and tab.Class) then
		return nil
	end
	
	local class=tab.Class
	local instance=Instance.new(class)
	if class=='NumberValue' or class=='IntValue' then
		instance.Value = tonumber(tab.Value)
	elseif class=='StringValue' then
		instance.Value = tab.Value
	elseif class=='BoolValue' then
		instance.Value = 'true'==tab.Value
	elseif class=='Color3Value' then
		instance.Value = Color3.new(unpack(tab.Value:split(',')))
	elseif class=='BrickColor' then
		instance.Value = BrickColor.new(tab.Value)
	elseif class=='CFrameValue' then
		instance.Value = CFrame.new(unpack(tab.Value:split(',')))
	elseif class=='Vector3Value' then
		instance.Value = CFrame.new(unpack(tab.Value:split(',')))
	end
	
	for name, obj in pairs(tab.children) do
		local child = table_to_userdata(obj)
		child.Name=name
		child.Parent=instance
	end
	
	return instance
end
1 Like

The formatting is off so it’s confusing but I think the original code works as intended.

1 Like

@greatgavin - Hi, yes. The original coding does work as intended, agreed the formatting is off and I am working on fixing it.

Ideally I am looking at how to save the Children of the values shown above so that I can keep my Folders categorised as opposed to having everything under a single folder.

@SuperSpeedy101 Oh yeah, u right. The if statement only on the Color3 threw me off.

@iiKossmoZ My bad about only color3 values being considered. lol, but again you still only perform recursion on your save function to the children of Configuration class objects. So I mean this would work if HairType and OutfitType were also Configurations. If you want the children of all types of objects to be considered, then you’ll need to store a table for each userdata object. The example I gave does do that. Feel free to look it over, try it out, and ask any questions.

1 Like

PM’ed you! ^^
[This dang thirty characters]

Why not have a table to organize everything?
I made a script that uses an organized method of serializing different datatypes by putting the functions in tables. For now, I only have a serializer and deserializer for the Color3 object.

local Serializers = {
    Color3 = function(Value)
        return string.format("%d,%d,%d", Value.R, Value.G, Value.B)
    end
}

local Deserializers = {
    Color3 = function(Value)
        return Color3.new(unpack(string.split(Value, ",")))
    end
}

function Serialize(Data)
    local SerializedData = {}
    for Name, Element in pairs(Data) do
        local DataType = typeof(DataType)
        if Serializers[DataType] then
            Element = DataType .. ":" .. Serializers[DataType](Value)
        end
        SerializedData[Name] = Element
    end
    return SerializedData
end

function Deserialize(SerializedData)
    local Data = {}
    for Name, Element in pairs(SerializedData) do
        local DataType, Value = unpack(string.split(Element, ":")) -- example: Color3:0,1,0
        if Deserializers[DataType] then
            Element = Deserializers[DataType](Value)
        end
        Data[Name] = Element
    end
    return Data
end
1 Like