Cannot store Array in DataStore when saving table

Hi!

I moved the table/main saving to the server, getting the new error.

I have spent a few hours trying to fix my DataStore, but nothing seems to work.

It cant save because I’m trying to save an array, but it’s just a table with the name + CFrame.

This is my save code.

function module.SaveData(player, plot, ID)
	game.ReplicatedStorage.Datastore.SaveHouse:FireServer( plot, ID)
end

--//ServerScript
game.ReplicatedStorage.Datastore.SaveHouse.OnServerEvent:Connect(function(Player, plot, ID)
	--// player : the player
	--// plot : the 'BuildPlot'
	local PlayerData = {}
	local BaseCFrame = game.Workspace.Plots[plot.Name].BuildPlot.CFrame
	local Data
	plot = game.Workspace.Plots[plot.Name].BuildPlot
	local function serializeCFrame(CF)
		return CF --idek anymore i'm so hungry and annoyed rn
	end
	for _, item in pairs(plot:GetChildren()) do
		if item:IsA("Model") then
			table.insert(PlayerData, {
				item.Name;
				table.pack(item.PrimaryPart.CFrame:GetComponents())
			})
		elseif item:IsA("MeshPart") or item:IsA("Part") or item:IsA("UnionOperation") then
			table.insert(PlayerData, {
				item.Name;
				serializeCFrame(item.CFrame)
			})
		end
	end
	print(Player.Name)
	local succ, err = pcall(function()
		DS:SetAsync(ID, PlayerData)
	end)
	if succ then print("Saved!") warn(DS:GetAsync(ID))return true elseif not succ then warn(err) return end
end)

When I load it, it seems to be returning nil, breaking it because InPairs cant have nil.
Thanks for any help!

1 Like

You can’t save CFrames in datastores. Replace return CF with

return {
    Position = {CF.X, CF.Y, CF.Z},
    Rotation = {CF:ToOrientation()}
}

And load it using

Object.CFrame = CFrame.new(table.unpack(Data.Position)) * 
                CFrame.Angles(table.unpack(Data.Rotation))
3 Likes

Is that tested? I’m pretty sure you can save every DataType expect for instances.

Well, even if it’s not possible (though I’m pretty sure it is), you can just do savedCframe = table.pack(cf:GetComponents()) to save it, and then do CFrame = CFrame.new(table.unpack(savedCFrame)).

Color3, BrickColor, Enum, Vector3, Vector2, UDim, UDim2, … all can’t be saved. Only;

  • Booleans

  • Strings

  • Numbers

  • Tables (arrays and dictionaries)

can be.

I guess I’ve never tried that myself, but yikes. That sounds like something that Roblox needs to get on.

Or something I could consider adding into my utility module, of which its purpose is to add or replace features as I see necessary…

I guess it has to do with keeping backend conversion for generally less used types for datastores minimal.

Sure, but it’s not like they couldn’t automatically convert it to plaintext and back. It would be pretty easy to do, which is why I think I will add that to my module (of which I will eventually release, I swear).

if item:IsA("Model") then
	table.insert(PlayerData, {
		item.Name;
		table.pack(item.PrimaryPart.CFrame:GetComponents())
	})
elseif item:IsA("MeshPart") or item:IsA("Part") or item:IsA("UnionOperation") then
	table.insert(PlayerData, {
		item.Name;
		serializeCFrame(item.CFrame)
	})
end

You just needed to make these consistent.

if item:IsA("Model") then
	table.insert(PlayerData, {
		item.Name;
		table.pack(item.PrimaryPart.CFrame:GetComponents())
	})
elseif item:IsA("BasePart") then
	table.insert(PlayerData, {
		item.Name;
		table.pack(item.CFrame:GetComponents())
	})
end

image
It works now, thanks!