How can I pass a function as an argument?

Hey devforum! How would I pass a function as an argument?

Here’s my code:
LocalScript:

-- Don't make the keycode F or else it will interfere with the flashlight
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ContextActionService = game:GetService("ContextActionService")

local Player = Players.LocalPlayer
local RemoteEvents = ReplicatedStorage:WaitForChild("RemoteEvents")
local InteractionSystemEevent = RemoteEvents:WaitForChild("InteractionSystemEvent")
local Mouse = Player:GetMouse()
local SelectionBox = script:WaitForChild("SelectionBox")

function MouseMoved()
	ContextActionService:UnbindAction(Player.Name.."Interaction")
	if Mouse.Target then
		local Object = Mouse.Target
		
		if Object:HasTag("CanInteract") then
			local InteractionInstructions = require(Object:WaitForChild("InteractionInstructions"))
			local Keycode = InteractionInstructions.Keycode
			local RunContext = InteractionInstructions.RunContext
			
			local function HandleAction(actionName, inputState, _inputObject)
				if actionName == Player.Name.."Interaction" and inputState == Enum.UserInputState.Begin then
					
					if RunContext == Enum.RunContext.Server then
						InteractionSystemEevent:FireServer(InteractionInstructions.InstructionsToCarryOut)
					elseif RunContext == Enum.RunContext.Client then
						InteractionInstructions.InstructionsToCarryOut()
					else
						warn(Object.Name..".InteractionInstructions.RunContext is invalid: Must be Enum.RunContext.Server or Enum.RunContext.Client")
					end
					
					SelectionBox.Parent = script
					SelectionBox.Adornee = nil
				end
			end
			
			SelectionBox.Parent = workspace
			SelectionBox.Adornee = Object
			ContextActionService:BindAction(Player.Name.."Interaction", 
										   	HandleAction,
											true,
											Keycode)
		elseif Mouse.Target == nil then
			SelectionBox.Parent = script
			SelectionBox.Adornee = nil
			ContextActionService:UnbindAction(Player.Name.."Interaction")
		else
			SelectionBox.Parent = script
			SelectionBox.Adornee = nil
		end
		
	end
	
end

Mouse.Move:Connect(MouseMoved)

ServerScript:

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local RemoteEvents = ReplicatedStorage:WaitForChild("RemoteEvents")
local InteractionSystemEevent = RemoteEvents:WaitForChild("InteractionSystemEvent")

function OnServerEvent(player, ...)
	({...})[1]()
end

InteractionSystemEevent.OnServerEvent:Connect(OnServerEvent)

I apologize if the code lacks comments or documentation as this project of mine is in it’s very early stages.

The InstructionsToCarryOut() function is a function without any arguments located inside of a ModuleScript in any part or model with the CanInteract tag that should be ran. Inside of the ModuleScript is also a RunContext variable which should decide whether it should be ran on the client or server to prevent using many RemoteEevents. There are 3 conditions which decide so and are located in the LocalScript. If the RunContext is set to the server then I want the InstructionsToCarryOut() function to be ran in the ServerScript using the RemoteEvent. I’m using a tuple and it doesn’t seem to be working. I keep getting a attempt to call a nil value error on Line 7 of the ServerScript.

Any help much appreciated!
Thank you in Advance.

1 Like

You cannot pass functions through RemoteEvents. In fact, you cannot pass a lot of things for security and technical reasons.

You can see the rules here:

P.S. having the server run code/functions that the client sends is a TERRIBLE idea, regardless of if it works or not. You are essentially creating a RAT (remote access trojan) in your game that exploiters can take advantage of. It’s the same reason why loadstring is disabled by default on the server and it gives off a warning if you turn it on. It’s all for the sake of your game’s security.

2 Likes

Ah. Didn’t know. Thanks for the advice.

Random fun fact: While protecting your game is one of the reasons it’s blocked, it is actually blocked to avoid exploiters passing a malicious function to the server and dumping RCCService. They can pass a non lua functions that can execute code in a lower level in Roblox’s servers which would lead to disaster.

That is actually wild to think of how easy it is do if it wasn’t blocked.