Can someone help me figure out how to serialize this data?

I’ve been trying for about a week to make a save slots system and I pretty much completed it, but I’ve been stuck at trying to save the folder and its descendants inside a table when the player leaves.

I read articles about serialization but I am having trouble figuring out how to implement it in my game.

This is the layout of the folders and values
img-2024-06-29-16-23-13
Each block contains blockId, Cframe, and Settings. If the block is wired to another object it contains inputObj which is the blockId of the input object. If the block is a control seat, it contains a folder called Keybinds which contains folders of all the blocks that are linked to the seat. Inside the block folders are string values.

Save/Load Script

local HttpService = game:GetService("HttpService")

local data = {}

local DataStore2 = require(game.ServerScriptService.Modules.DataStore2)
DataStore2.Combine("DATA", "SaveSlots")

function data.load(player, abletosave)
	local folder = player:WaitForChild("Save Slots")

	local SlotsTable = {}

	local SlotsStore = DataStore2("SaveSlots", player)
	SlotsTable = SlotsStore:Get()
	print(SlotsTable)
	if SlotsTable then
		--This is where it is supposed to convert the table back into folders and values
	end
	abletosave.Value = true
end

function data.save(player, abletosave)
	local SaveSlots = player:WaitForChild("Save Slots")
	
	if abletosave.Value == true then
		local SlotsStore = DataStore2("SaveSlots", player)
		
		local slots = {}
		
		--I can't figure out how to convert the folder's descendants into a table here
		
		SlotsStore:Set(SaveSlots)
	end
end

return data
1 Like
function serializeFolder(folder: Folder)
	local result = {}
	
	for _, object in folder:GetChildren() do
		if object:IsA('ValueBase') then --the class of value objects
			
			--necessary as datastore can only save bool,string,number
			local isValueSavable = type(object.Value) ~= 'userdata'
			result[object.Name] = 
				if isValueSavable then object.Value else tostring(object.Value)
			
		
		elseif object:IsA('Folder') then
			result[object.Name] = serializeFolder(object)
		end
	end
	
	return result
end

it would give you this result:

print(serializeFolder(workspace["Save Slot #1"]))
--[[
{
   ["ControlSeat"] =  ▼  {
      ["Cframe"] = "0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1",
      ["Keybinds"] =  ▼  {
         ["Light"] =  ▼  {
            ["Activate"] = "keybind",
            ["Light"] = "keybind"
         }
      },
      ["Settings"] =  ▼  {
         ["Anchored"] = false,
         ["BoatControl"] = false,
         ["CanCollide"] = false,
         ["Transparency"] = 0
      },
      ["blockId"] = 0
   },
   ["Light"] =  ▼  {
      ["Cframe"] = "0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1",
      ["Settings"] =  ▼  {
         ["Anchored"] = false,
         ["CanCollide"] = false,
         ["Transparency"] = 0
      },
      ["blockId"] = 0,
   },
   ["WoodPlanks"] =  ▼  {
      ["Cframe"] = "0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1",
      ["Settings"] =  ▼  {
         ["Anchored"] = false,
         ["CanCollide"] = false,
         ["Transparency"] = 0
      },
      ["blockId"] = 0,
   }
}
]]

must note that this specific example ^ has a problem
It doesn’t work if children share the same name, as it would overwrite the previous key in the dictionary.

which could be solved by saving children as an array rather than a dictionary, but then you must save extra data related to the name of the instance, the classtype, etc.

I would recommend looking into a serialization library if you can’t come up with a structure that would make it easy for you to reconstruct the objects back from

like this one:

1 Like

I was able to get it to work using the module, but I have one more question. Should I save each save slot in a different datastore key, or would it be fine to save them all in one key?

yeah… it’s fine to save in a single key

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.