Local Script to Server Script Problem (Remote Functions)

I’m trying to load some homes saved in a datastore on a local script, it does use a remote function to a server script, the data is returned using return in the remote function’s definition.

The issue is it seems to do everything up to loading the home, except it doesn’t load the home.

I assume the problem could be related to the way I get the datastore data, which would be by the remote functions, though I researched and what I saw said I could use return in the definition of a remote function.

I’m so sorry for how long this script is, it is a local script by the way. The save home, load home functions used to be in a module script though module scripts have a lot of errors loading on the local player so I decided to just move the code into the same script in the player.

local player = game.Players.LocalPlayer
local RequestHttp = player:WaitForChild("RequestHttp")
local RequestHomeData = player:WaitForChild("RequestHomeData")

function SaveHome(block, owner, index, Home)
	if Home then
		local player = game:GetService("Players"):GetPlayerByUserId(owner)
		player.HomePosition.Value = Home.Parent.Parent.Default.Road:FindFirstChild("Plot" .. index).Position
		player.OwnedHome.Value = block .. ":" .. index
		print("Saving home " .. block .. ":" .. index .. "...")

		local HomeData = { Owner = tonumber(owner), Objects = {} }
		for _, child in pairs(Home:GetChildren()) do
			table.insert(HomeData.Objects, {
				Name = child.Name,
				Position = { child.PrimaryPart.Position.X, child.PrimaryPart.Position.Y, child.PrimaryPart.Position.Z },
				Orientation = { child.PrimaryPart.Orientation.X, child.PrimaryPart.Orientation.Y, child.PrimaryPart.Orientation.Z }
			})
		end
		local success, result = pcall(function()
			wait(0.5)
			RequestHomeData:InvokeServer("Set",block .. ":" .. index,RequestHttp:InvokeServer("Encode",HomeData))
		end)
		if success then
		else
			print("Home " .. block .. ":" .. index .. " ERR SAVING!")
		end
	else
		wait(5)
		SaveHome(block,owner,index,Home)
	end
end

function LoadHome(block, i, player)
	local _HomeData = RequestHomeData:InvokeServer("Get",block .. ":" .. i)
	if _HomeData then
		local HomeData = RequestHttp:InvokeServer("Decode",_HomeData)
		local NewHome = game.ReplicatedStorage.Home:Clone()

		NewHome.Name = tostring(block .. ":" .. i)

		for _, Block in pairs(workspace.Blocks:GetChildren()) do
			if block == Block.Name then
				NewHome.Parent = Block.Homes
				--NewHome:PivotTo(CFrame.new(Block.Road:WaitForChild("Plot" .. i).Position.X, 0, Block.Road:WaitForChild("Plot" .. i).Position.Z))
				break
			end
		end

		if HomeData.Objects then
			for _, value in pairs(HomeData.Objects) do
				print(value.Name)
				local object = game.ReplicatedStorage.Objects:FindFirstChild(value.Name):Clone()
				object.Parent = NewHome
				object.Name = value.Name
				object.PrimaryPart.Position = Vector3.new(value.Position[1], value.Position[2], value.Position[3])
				object.PrimaryPart.Orientation = Vector3.new(value.Orientation[1], value.Orientation[2], value.Orientation[3])
				--object.PrimaryPart:UnionAsync(object.PrimaryPart:GetTouchingParts(),Enum.CollisionFidelity.PreciseConvexDecomposition,Enum.RenderFidelity.Precise)
			end
		end

		for _, child in pairs(NewHome:GetChildren()) do
			for _, _child in pairs(child:GetChildren()) do
				_child.Transparency = 1
				local info = TweenInfo.new(3, Enum.EasingStyle.Exponential)
				local goal = { Transparency = 0 }
				local Tween = game:GetService("TweenService"):Create(_child, info, goal)
				Tween:Play()
			end
		end

		-- Connect the ChildAdded event to save the home
		NewHome.ChildAdded:Connect(function(child)
			SaveHome(block, player, i, NewHome)
		end)
		NewHome.ChildRemoved:Connect(function(child)
			SaveHome(block, player, i, NewHome)
		end)

		SaveHome(block, player, i, NewHome)
	else
		local NewHome = game.ReplicatedStorage.DefaultHome:Clone()
		NewHome.Name = tostring(block .. ":" .. i)

		for _, Block in pairs(workspace.Blocks:GetChildren()) do
			if block == Block.Name then
				NewHome.Parent = Block.Homes
				--NewHome:PivotTo(CFrame.new(Block.Default.Road:WaitForChild(i).Position.X, 0, Block.Default.Road:WaitForChild(i).Position.Z))
				break
			end
		end

		for _, child in pairs(NewHome:GetChildren()) do
			child.Transparency = 1
			local info = TweenInfo.new(3, Enum.EasingStyle.Exponential)
			local goal = { Transparency = 0 }
			local Tween = game:GetService("TweenService"):Create(child, info, goal)
			Tween:Play()
		end

		-- Connect the ChildAdded event to save the home
		NewHome.ChildAdded:Connect(function(child)
			SaveHome(block, player.UserId, i, NewHome)
		end)
		NewHome.ChildRemoved:Connect(function(child)
			SaveHome(block, player.UserId, i, NewHome)
		end)

		SaveHome(block, player, i, NewHome)
	end
end

function LoadHomes(block)
	print("Loading homes")
	for i = 1, 4 do
		local _HomeData = RequestHomeData:InvokeServer("Get",block .. ":" .. i)
		print(RequestHomeData:InvokeServer("Get",block .. ":" .. i))
		if _HomeData then
			local HomeData = RequestHttp:InvokeServer("Decode",_HomeData)
			LoadHome(block, i, HomeData.Owner)
		else
			local ProxPrompt = Instance.new("ProximityPrompt")

			for _, Block in pairs(workspace.Blocks:GetChildren()) do
				if block == Block.Name then
					ProxPrompt.Parent = Block.Default.Road:FindFirstChild(i)
				end
			end

			ProxPrompt.Triggered:Connect(function(player)
				if player.leaderstats.Silver.Value >= 2000 and player.Homes.Value < 1 then
					player.leaderstats.Silver.Value -= 2000
					player.Homes.Value += 1

					ProxPrompt.Enabled = false
					LoadHome(block, i, player)
				end
			end)
		end
	end
end

-- Define chunk size (adjust as needed)
local BLOCK_SIZE = 100

-- Math
local function RoundToNearestTen(number)
	return math.round(number / BLOCK_SIZE) * BLOCK_SIZE
end

local function GetBlockFromPosition(position)
	if math.round(position.X/100) == -0  then
		return Vector3.new(0,0,math.round(position.Z/100))
	elseif math.round(position.Z/100) == -0 then
		return Vector3.new(math.round(position.X/100),0,0)
	elseif math.round(position.X/100) == -0 and math.round(position.Z/100) == -0 then
		return Vector3.new(0,0,0)
	else
		return Vector3.new(math.round(position.X/100),0,math.round(position.Z/100))
	end
end

local function GetBlockPositionFromCoords(coordinates)
	local XY = string.split(coordinates)
	return Vector3.new(tonumber(XY[1]), 0, tonumber(XY[2]))
end

local function LoadAndCheck(blockToLoad)
	for i = 1,4 do
		local block = blockToLoad.X .. "," .. blockToLoad.Z
		local homeName = block..":"..i

		if workspace.Blocks:FindFirstChild(homeName,true) then
		else
			local _HomeData = RequestHomeData:InvokeServer("Get",homeName)
			if _HomeData then
				local HomeData = RequestHttp:InvokeServer("Decode",_HomeData)
				LoadHome(block, i, HomeData.Owner)
			end
			break
		end
	end
end

local function LoadOffsets(block)
	local offsets2 = {
		Vector3.new(1, 0, 0),
		Vector3.new(-1, 0, 0),
		Vector3.new(0, 0, 1),
		Vector3.new(0, 0, -1),
		Vector3.new(1, 0, 1),
		Vector3.new(-1, 0, -1),
		Vector3.new(-1, 0, 1),
		Vector3.new(1, 0, -1),

		Vector3.new(2, 0, 0),
		Vector3.new(-2, 0, 0),
		Vector3.new(0, 0, 2),
		Vector3.new(0, 0, -2),
		Vector3.new(2, 0, 2),
		Vector3.new(-2, 0, -2),
		Vector3.new(-2, 0, 2),
		Vector3.new(2, 0, -2),

		Vector3.new(-1, 0, -2),
		Vector3.new(-1, 0, 2),
		Vector3.new(1, 0, -2),
		Vector3.new(1, 0, 2),
		Vector3.new(-2, 0, 1),
		Vector3.new(2, 0, -1),
		Vector3.new(-2, 0, -1),
		Vector3.new(2, 0, 1)

	}

	local offsets1 = {
		Vector3.new(1, 0, 0),
		Vector3.new(-1, 0, 0),
		Vector3.new(0, 0, 1),
		Vector3.new(0, 0, -1),
		Vector3.new(1, 0, 1),
		Vector3.new(-1, 0, -1),
		Vector3.new(-1, 0, 1),
		Vector3.new(1, 0, -1),
	}

	for _, offset in ipairs(offsets2) do
		local targetBlock = Vector3.new(block.X + offset.X, 0, block.Z + offset.Z)
		if targetBlock ~= Vector3.new(0, 0, 0) then
			LoadAndCheck(targetBlock)
		end
	end
end

player.CharacterAdded:Connect(function(character)
	local rootPart = character:WaitForChild("HumanoidRootPart",10)

	local Dead = false

	player.CharacterRemoving:Connect(function()
		Dead = true
	end)

	repeat
		wait(0.1)
		local block = GetBlockFromPosition(rootPart.Position)

		-- Exclude the origin block (0,0,0)
		if block ~= Vector3.new(0, 0, 0) then

			LoadAndCheck(block)
			LoadOffsets(block)

		else
			LoadOffsets(block)
		end
	until Dead == true
end)

Can you elaborate on what you mean by this? Is the server failing to pull any data from the data store? Is the data modified when it gets sent back to the client from the server? etc.

Based on your code snippet, it’s a bit difficult to know what exactly might be going wrong. What I would do to narrow down the issue would be to just go step by step in your loading flow and confirm whether it’s working or not. You could do something like the following:

  1. Ensure the data is being retrieved from the data store correctly on the server
  2. Ensure the data is properly transferred back to the client from the server
  3. Ensure LoadHome works based on _HomeData received from the server (assuming any data is actually received)

Sorry I forgot to take down this thread. I did fix the problem, I’m not sure what was wrong with it but instead of doing all the stuff on the client and using the server for the datastore, I decided to run everything on the server and use the client for checking things in the local workspace, and loading in local copies of parts.

1 Like

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