RemoteFunction not returning a value

This issue was covered back in '19 on this thread, but it seems Lua has changed since then. 2019 thread is at RemoteFunction not returning a value

I’m trying to get the values of three server-side BoolValue objects (BoolValue.Value) stored under game.Players.(some player name here), in a folder called “Settings”, via using RemoteFunction. This is so I can modify game behavior based on what my users want as their controls (for example, re-binding sprinting to “Z” to allow for shift mouse lock compatibility).

However, it seems that when I make use of the solution in the 2019 thread on this issue (linked above), my script hangs infinitely on the server side (it only prints up to “event fired” before halting w/o an error message).

While this doesn’t make my game actually unplayable, it’s really annoying to see how my game’s menu shows completely inaccurate information. Does anyone have help for this day and age?

Server script (PlayerOptionsFE):

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local SettingsFolder = script.Settings

function AddSettings(player)
	
	if player:FindFirstChild("Settings") == nil then
		wait()
		local Setting2 = SettingsFolder:Clone()
		Setting2.Parent = player

		print("settings added to player " .. player.Name)
	else
		warn("Tried to add another settings folder to player " .. player.Name .. " when one already exists!")
	end
	
end

function ApplySettings(player,newSettings)
	if player:IsA("Player") then
		pcall(function()
			local Settings = player:WaitForChild("Settings")
			Settings.ZSprint.Value = newSettings[1]
			Settings.SprintToggle.Value = newSettings[2]
			Settings.MusicMute.Value = newSettings[3]
		end)
	end
end

function GetSettings(player)
	warn("fired")
	local be = Instance.new("BindableEvent",game.Workspace)
	warn("event created")
	local ReturnedSettings = { }
	if player:IsA("Player") then
		warn("is a player")
		pcall(function()
			warn("pcall entered")
			local Settings = player:WaitForChild("Settings")
			table.insert(ReturnedSettings,1,Settings.ZSprint.Value)
			table.insert(ReturnedSettings,2,Settings.SprintToggle.Value)
			table.insert(ReturnedSettings,3,Settings.MusicMute.Value)
			warn("inserted table items")
			
			warn(tostring(ReturnedSettings[1]) .. "," .. tostring(ReturnedSettings[2]) .. "," .. tostring(ReturnedSettings[3]))

			be:Fire(ReturnedSettings)
			warn("event fired")
		end)
		local result = be.Event:Wait()
		warn("result obtained")
		warn(tostring(result[1]) .. "," .. tostring(result[2]) .. "," .. tostring(result[3]))
		be:Destroy()
		warn("event destroyed")
		return result
	else
		return nil
	end
end

game.Players.PlayerAdded:Connect(AddSettings)
ReplicatedStorage.PlayerOptionsFE.GetOptions.OnServerInvoke = GetSettings
ReplicatedStorage.PlayerOptionsFE.ApplyOptions.OnServerEvent:Connect(ApplySettings)

Client script (MenuMain):

local player = game.Players.LocalPlayer -- Get the currently active player (client side)
local ReplicatedStorage = game:GetService("ReplicatedStorage")

function GetMenuOptions()
	local Settings = ReplicatedStorage.PlayerOptionsFE.GetOptions:InvokeServer()
	warn(tostring(Settings))
	warn(tostring(Settings[1]) .. "," .. tostring(Settings[2]) .. "," .. tostring(Settings[3]))
	
	if Settings == nil then return false end -- Never trust the client...

	if Settings[1] == true then
		script.Parent.MenuGUI.OptionMenu.Button_ZSprint.BackgroundColor3 = Color3.fromRGB(0, 170, 0)
		script.Parent.MenuGUI.OptionMenu.Button_ZSprint.Text = "ENABLED"
	end
	if Settings[2] == true then
		script.Parent.MenuGUI.OptionMenu.Button_SprintMode.BackgroundColor3 = Color3.fromRGB(0, 170, 0)
		script.Parent.MenuGUI.OptionMenu.Button_SprintMode.Text = "ENABLED"
	end
	if Settings[3] == true then
		script.Parent.MenuGUI.OptionMenu.Button_MuteMusic.BackgroundColor3 = Color3.fromRGB(0, 170, 0)
		script.Parent.MenuGUI.OptionMenu.Button_MuteMusic.Text = "ENABLED"
	end
end

function SetMenuOptions(ZSprint,SprintToggle,MusicMute)
	local Settings = { }
	table.insert(Settings,1,ZSprint)
	table.insert(Settings,2,SprintToggle)
	table.insert(Settings,3,MusicMute)
	
	ReplicatedStorage.PlayerOptionsFE.ApplyOptions:FireServer(Settings)
end

if player.TeamColor == game.Teams.Choosing.TeamColor then -- Verifies that the player just joined the game or triple pressed "X"
	local character = player.Character
	local camera = game.Workspace.CurrentCamera

	repeat wait()
		camera.CameraType = Enum.CameraType.Scriptable
	until camera.CameraType == Enum.CameraType.Scriptable

	player.Backpack:ClearAllChildren()
	camera.CFrame = game.Workspace.Menu_CameraPos.CFrame
	game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.All,false)
	script.Parent.MenuGUI.Enabled = true
	script.Parent.MenuGUI.Music:Play()
	GetMenuOptions()
end

script.ApplySettings.Event:Connect(SetMenuOptions)

If anyone needs additional context, I’m willing to provide all the scripts/events/etc involved in an empty baseplate *.rbxl file for people to mess around with. Thanks for any help that you can provide.

Many thanks,
–Catz.

PS: If I don’t reply immediately, I’m either in school or asleep. Please be patient with me if I’m delayed with my responses (or misunderstanding your code).

If Im understanding your code correctly, the bindable event would be fired before you even start listening for it
Assuming youre trying to wait for the end of the pcall for the rest of the code to continue, you do not have to do this
pcalls run in the same thread as what they’re in

Yeah, well, that’s what I believe the 2019 thread is saying to do, and it worked back then. Doesn’t work now though.

So is what you’re saying to move be:Fire(ReturnedSettings) outside the pcall() or am I missing something here?

I would entirely remove the bindable event related code, as its not necessary for proper ordering of the script

1 Like

Huh, for some reason it just mysteriously started working.

function GetSettings(player)
	warn("fired")
	local ReturnedSettings = { }
	if player:IsA("Player") then
		warn("is a player")
		pcall(function()
			warn("pcall entered")
			local Settings = player:WaitForChild("Settings")
			table.insert(ReturnedSettings,1,Settings.ZSprint.Value)
			table.insert(ReturnedSettings,2,Settings.SprintToggle.Value)
			table.insert(ReturnedSettings,3,Settings.MusicMute.Value)
			warn("inserted table items")
		end)
		
		warn(tostring(ReturnedSettings[1]) .. "," .. tostring(ReturnedSettings[2]) .. "," .. tostring(ReturnedSettings[3]))
		
		return ReturnedSettings
	else
		return nil
	end
end

I think the actual reason my code wasn’t working as intended was possibly because I put return ReturnedSettings and by extension local ReturnedSettings = { } in the pcall() block in the original code before I tried the fix from the 2019 thread, could that have potentially impeded things?

EDIT: Screenshot of output
image_2021-04-25_223142