House Saving and Loading not working properly

Include a standalone, bare-bones rbxl file with only the code you want reviewed.
HouseSaveAndLoad.rbxl (128.6 KB)

Provide an overview of:

  • What does the code do and what are you not satisfied with?
  • What potential improvements have you considered?
  • How (specifically) do you want to improve the code?

The “HouseSaving” script in ServerScriptService saves the relative position and orientation of all of the furniture items in the player’s house.
The Script in workspace.HouseClaims.ClaimHouse.Part is supposed to load that information.
For some reason the furniture objects aren’t rotated correctly, and the position is offset, as well.

I’ve tried adding offsets to the position and rotation, saving it globally instead of locally, and generally tinkering with both the saving and loading.

House Saving
local Players = game:GetService("Players")
local dss = game:GetService("DataStoreService")
local https = game:GetService("HttpService")

--local data = dss:GetDataStore("house")

Players.PlayerAdded:Connect(function(Player)
	local house_predata = Instance.new("StringValue")
	house_predata.Parent = Player
	house_predata.Name = "HouseData"
	-- Setting save data manually because you can't access DataStores without saving.
	house_predata.Value = '{"houseinfo":{"secondfloor":false,"hasTV":false},"furniture":[["Table",[0.087554931640625,-3.916909694671631,1.6467056274414063],[0.054831139743328097,-1.5435249470174313,0.05444833263754845]],["Lamp",[-0.069915771484375,-6.235631942749023,2.1008834838867189],[0.054831136018037799,-1.5414111856371165,-0.027777763083577157]],["Chair",[4.241077423095703,-2.221060276031494,-5.83742094039917],[0.03729011490941048,-1.8467627465724946,-0.33965957164764407]]]}'
	
	--[[
	local success, exception = pcall(function()
		local save = data:GetAsync(Player.UserId)
		if not save then return false, "No Save Data" end
		house_predata.Value = save
	end)
	
	if not success then
		warn("Data load error: ", exception)
	end
	]]--
end)

local function savedata(player:Player)
	local save = {}
	save.houseinfo = {
		secondfloor = false,
		hasTV = false}
	save.furniture = {}
	
	local originCFrame:CFrame = nil
	
	local house = nil
	for i, v:Model in pairs(workspace:WaitForChild("PlayerHouses"):GetChildren()) do
		local owner = v:FindFirstChild("Owner") :: StringValue
		if owner.Value == player.Name then
			house = v
			originCFrame = v:GetPivot()
			break
		end
	end
	
	if house == nil then return end
	
	for i, v:Model in pairs(house:WaitForChild("Furniture"):GetChildren()) do
		local relativePosition = originCFrame.Position - v:GetPivot().Position
		local x, y, z = v:GetPivot():ToEulerAnglesXYZ()
		local x2, y2, z2 = originCFrame:ToEulerAnglesXYZ()
		local rotation = {x, y, z}
		local rotation2 = {x2, y2, z2}
		local relativeRotation = {
			rotation2[1] - rotation[1],
			rotation2[2] - rotation[2],
			rotation2[3] - rotation[3]}

		table.insert(save.furniture, {v.Name, {relativePosition.X, relativePosition.Y, relativePosition.Z}, relativeRotation})
	end
	
	if not house:FindFirstChild("Roof") then
		save.houseinfo.secondfloor = true
	end
	
	if house.TV.Screen.Transparency == 0 then
		save.houseinfo.hasTV = true
	end
	
	local success, exception = pcall(function()
		--data:SetAsync(player.UserId, https:JSONEncode(save))
		print("SAVE DATA: ", https:JSONEncode(save))
	end)

	if not success then
		warn("Data save error: ", exception)
	end
	
	house:Destroy()
end

game:BindToClose(function()
	for i, v in pairs(game.Players:GetPlayers()) do
		savedata(v)
	end
end)

game.Players.PlayerRemoving:Connect(function(player: Player)
	savedata(player)
end)
House Loading
local Debounce = true
local ClaimHouse = game.ReplicatedStorage.Events:WaitForChild("ClaimHouse")
local Players = game:GetService("Players")

local https = game:GetService("HttpService")
local rs = game:GetService("ReplicatedStorage")

local function ClaimedHouse()
	script.Parent.Transparency = 1
	script.Parent.BillboardGui.Enabled = false
	script.Parent.CanTouch = false
end

script.Parent.Touched:Connect(function(HitPlayer)
	if not HitPlayer.Parent or not HitPlayer.Parent:FindFirstChild("Humanoid") then return end
	if Debounce == true and HitPlayer.Parent.Humanoid.Health > 10 then
		Debounce = false
		local Player = Players:GetPlayerFromCharacter(HitPlayer.Parent)
		local House = game.ReplicatedStorage.House:Clone()
		task.wait(0.25)
		House.Sign.SurfaceGui.TextLabel.Text = (Player.Name.."'s House")
		House:PivotTo(script.Parent.Pos.CFrame)
		House.Parent = game.Workspace.PlayerHouses
		ClaimHouse:FireClient(Player, House)
		House.Owner.Value = Player.Name
		print(House.Owner.Value)
		
		-- LOAD HOUSE
		
		local house_position = House:GetPivot().Position
		local house_rotation = House:GetPivot().Rotation
		
		local house_data = Player:WaitForChild("HouseData").Value
		if house_data ~= "{}" then
			local house_json = https:JSONDecode(house_data)
			print("HOUSE INFO: ", house_json.houseinfo)
			print("HOUSE FURN: ", house_json.furniture)
			for index, value in pairs(house_json.furniture) do
				print(index, value)
				local furniture_type = value[1]
				local furniture_position = value[2]
				local furniture_rotation = value[3]
				
				if rs.Furniture:FindFirstChild(furniture_type) then
					local new_furniture:Model = rs.Furniture:FindFirstChild(furniture_type):Clone()
					local px,py,pz = furniture_position[1], furniture_position[2], furniture_position[3]
					local furn_pos = house_position - Vector3.new(px, py, pz)
					local rx,ry,rz = furniture_rotation[1], furniture_rotation[2], furniture_rotation[3]
					new_furniture:PivotTo(CFrame.new(furn_pos) * CFrame.Angles(
						math.rad(house_rotation.X + rx),
						math.rad(house_rotation.Y + ry),
						math.rad(house_rotation.Z + rz)))
					for i, v in pairs(new_furniture:GetChildren()) do
						v.Anchored = true
					end
					new_furniture.Parent = House.Furniture
				end
			end
		end

		
		ClaimedHouse()
	end
end)

1 Like