How to save Build Mode

Hey there, developers!

I want to know, how do you save Part’s names and their positions,

I have tried converting it to a string then converting it to a number, but that was unsuccessfull.

Here are my scripts:

Saver:

local ds = game:GetService("DataStoreService"):GetDataStore("Build")

game.Players.PlayerRemoving:Connect(function(player)
	for i,v in pairs(workspace.BlocksPlaced:GetChildren()) do
		if v.Name == "PlacedBlock" then
			local name = tostring(v:GetAttribute("Name"))
			
			local async = ds:GetAsync(player.UserId)
			
			local pos = tostring(v.Position)
			table.insert(async, {name, pos})
			
			ds:SetAsync(player.UserId, async)
			
		end
	end
end)

Loader:

local ds = game:GetService("DataStoreService"):GetDataStore("Build")

game.Players.PlayerAdded:Connect(function(player)
	local async = ds:GetAsync(player.UserId)
	if async then
		for i,v in pairs(async) do
			print(tonumber(async[v]))
			print(tonumber(async[v][1]))
			print(tonumber(async[v][2]))
			local blockFound = game.ServerStorage.Models:FindFirstChild(tonumber(async[v][1]))

			local clone = blockFound:Clone()

			clone.Position = Vector3.new(tonumber(async[v][2]))
		end
	end
end)

I am not good at Build Modes, so any help is appreciated.

(i am going offline so i won’t be able to respond but i can after school tomorrow!)

3 Likes

I’m not sure why you want to save the CFrame as a string. The name of the object should already be a string.

3 Likes

Here’s a way that works:

local CF = CFrame.new()
local data = {CF:GetComponents()}
--you can save it now
local savedCF = CFrame.new(unpack(data))
2 Likes

What does the CF do? I’ve never seen situations where i only used CFrame.new()

1 Like

CFrame.new() just returns a CFrame where all the components are 0.

1 Like

If you’re storing positional values in Datastore use position instead with a separate rotation value. Also, if you’re building game uses a grid you can just divide your position by your grid size and save that.

2 Likes

CF is just a variable. That code is just an example howing how I can get a CFrame (in this example, the variable CF), convert it into a table (which you can save), then convert it back into a CFrame (whenever you wanna load the data)

1 Like

You will need to make your own CFrame using a table. For saving, use

local pos = {v.Position.X, v.Position.Y, v.Position.Z, v.Orientation.X, v.Orientation.Y, v.Orientation.Z}

No tostring()'s needed.

And for loading:

clone.CFrame = CFrame.new(async["Position"][1], async["Position"][2], async["Position"][3])*CFrame.fromEulerAnglesXYZ(math.rad(async["Position"][4]), math.rad(async["Position"][5]), math.rad(async["Position"][6]))

Let me know if that helps :slight_smile:

1 Like

Unfortunately, i cannot test this now, but i might be able to tommorow since i have a bad migraine :slight_smile:

1 Like
-- save data
local data = {cFrame:GetComponents()}
ds:SetAsync(key, data)

-- get data
local unpacked = unpack(ds:GetAsync(key) or {})
block.CFrame = CFrame.new(unpacked)
1 Like

that’s not all the components of a CFrame, so that won’t work.

1 Like

It works in my code, and he is doing something similar, so I see no reason why it shouldn’t work.

1 Like

Hey friend, you might want to look into Instance DataStore!
https://devforum.roblox.com/t/instancedatastore-save-any-instance-easily/955399

1 Like

I’ve just tried implementing that into my code, it seems to not work, here is the code:

my module (i made it so that when you place an object, it updates the datastore)

function module.place(block, mouse, player)
	if mouse then
		local clone = block:Clone()
		print(mouse.Name)

		if mouse:GetAttribute("PartAbove") == false then
			if mouse.Name == "PlacedBlock" then
				print'no'
				clone.Parent = workspace.BlocksPlaced
				local cha = clone.Size.Y
				print(cha)
				clone:SetAttribute("Creator", player.Name)
				clone.CFrame = mouse.CFrame +Vector3.new(0,cha,0)
				clone.Name = "PlacedBlock"
				
				mouse:SetAttribute("PartAbove", true)
				
				local name = tostring(clone:GetAttribute("Name"))
				
				local pos = {clone.Position.X, clone.Position.Y, clone.Position.Z, clone.Orientation.X, clone.Orientation.Y, clone.Orientation.Z, clone:GetAttribute("Name")}
				
				local info = ds:GetAsync(player.UserId)
				
				if info then
					table.insert(info, pos)
				else
					local i = {pos}
					
					
				end
				wait()
				ds:SetAsync(player.UserId, info)
				print'done'
			else
				clone.Parent = workspace.BlocksPlaced
				local cha = clone.Size.Y/2
				print(cha)
				clone:SetAttribute("Creator", player.Name)
				clone.CFrame = mouse.CFrame +Vector3.new(0,cha,0)
				clone.Name = "PlacedBlock"
				
				local name = tostring(clone:GetAttribute("Name"))

				local pos = {clone.Position.X, clone.Position.Y, clone.Position.Z, clone.Orientation.X, clone.Orientation.Y, clone.Orientation.Z, clone:GetAttribute("Name")}

				local info = ds:GetAsync(player.UserId)

				if info then
					table.insert(info, pos)
				else
					local i = {pos}


				end
				wait()
				ds:SetAsync(player.UserId, info)
			end
		end


	end


end

script: (loader)

local ds = game:GetService("DataStoreService"):GetDataStore("Build")

game.Players.PlayerAdded:Connect(function(player)
	local async = ds:GetAsync(player.UserId)
	if async then
		for i,v in pairs(async) do
			local blockFound = game.ServerStorage.Models:FindFirstChild(tostring(async[v][1]))

			local clone = blockFound:Clone()

			clone.CFrame = CFrame.new(async["Position"][1], async["Position"][2], async["Position"][3])*CFrame.fromEulerAnglesXYZ(math.rad(async["Position"][4]), math.rad(async["Position"][5]), math.rad(async["Position"][6]))
			clone.Name = "PlacedBlock"
			clone.Parent = workspace.BlocksPlaced
			clone:SetAttribute("Name", async["Name"][7])
		end
	end
end)

There is an error here:

local blockFound = game.ServerStorage.Models:FindFirstChild(tostring(async[v][1]))

the error is

  ServerScriptService.Loader:7: attempt to index nil with number