Sending function from server, but it's nil for client

This is an issue I’ve had from the start and have no clue how to fix:

Summary: I have admin. If admin runon setting is on the client, it sends it to the client with a remote function. the client, receives the arguements, and the function itself. But when I print the function, I should get something like function: 30dxcgr3r9fd84 but i get nil. I don’t want to make the commands available to the client because then people would steal it. I’ve been able to get it to work sometimes, which leads me to believe I’m doing something wrong. But unsure.

This is the command within the module script

Info.Commands.View = {
	["command"] = ":view",
	["ranon"] = "client",
	["arguements"] = 2,
	["requirement"] = 1,
	["execute"] = function(player, PlayerToView)
		local StopLoop = false
		local Camera = workspace.CurrentCamera
		local success, errormsg = pcall(function()
			for i,v in pairs(game.Players:GetPlayers()) do
				if StopLoop == false then
					if string.match(string.lower(v.Name), string.lower(PlayerToView)) then
						StopLoop = true
						local PlayerToView = v.Character
						Camera.CameraSubject = PlayerToView.Humanoid
						Camera.CameraType = "Custom"
						Camera.CFrame = PlayerToView.Head.CFrame
					end
				end
			end
		end)
		print(success, errormsg)
		if success and StopLoop then
			return "Executed"
		elseif not StopLoop then
			return "PlayerNotFound"	
		elseif errormsg then
			return {"Error", errormsg}
		else
			return "Fail"
		end	
	end
}

Server Sided Execution

local function HandleExecution(plr, Ranon,Execute,A)
	local ChatArguements = A
	table.remove(ChatArguements, 1)
	local FunctionResult
	if Ranon == "server" then
		FunctionResult = Execute(plr, table.unpack(ChatArguements))
	elseif Ranon == "client" then
		FunctionResult = ClientExecution:InvokeClient(plr, Execute, ChatArguements)
	else 
		print('error in execution, nor server nor client')
	end
	
	
	for i,v in pairs(CommandResponses) do
		if i == FunctionResult or i == FunctionResult[1] then
			print(i,v,FunctionResult)
			if v.Type == "Success" then
				ErrorSuccessCommunicate:InvokeClient(plr,"Success", nil)
			elseif i == "Error" then
				ErrorSuccessCommunicate:InvokeClient(plr, "Error", FunctionResult[2])
			else
				ErrorSuccessCommunicate:InvokeClient(plr, "Error", v.Message)
			end
		end
	end
end

Client Side Execution

RepStor.AdminEvents.ClientExecution.OnClientInvoke = function(executeFunction, args)
	print(executeFunction,args)
	if not args then
		args = {}
	end
	local Result = executeFunction(game.Players.LocalPlayer, table.unpack(args))
	return Result
end

Picture of printing functions and arguements:
image

Client sided error image:

I assume it has something to do with the nil print because I have a print outside of the pcall in the command, and it’s not printing at all.

Any help is greatly appreciated.

1 Like

Is the module script in ServerScriptService or ServerStorage? I’d also read this, see Parameter Limitations.

The modules are in the SSS, along with the loader, and everything else.

I was hoping to send the function by sending it, “itself” but it seems to just be sending the table “position” instead of the function.

I really don’t want the client to have access to the commands, because I’m sure as hell someone will steal it.

I may be way off here but I don’t think you can send a table/array between client and server. You need to send the individual arguments as variables.

Nope, you can send arrays/tables perfectly fine. This is the client printing out the table.
image

My issue is that the function sent is nil. : | I just added a print function to the server loader/executor and it prints fine. It’s just the server/client sending the function that’s the issue. The command has worked before some of the time and I’m not sure why, but I do get errors.

image

So I looked at the parametes and it say: If any indices of a passed table are non-string type ( Instance , userdata, function, another table, etc.), those indices will be converted to a string.

And it should work if it’s converted to a string. So why would it be nil?

I’ve tested this, and the tables that contain instances that are replicated to the client, such as workspace instances or replicated storage stuff, it doesn’t turn those indices into a string. But if I pass a table with indices that are descendants of either ServerScriptService or ServerStorage, those indexes are replaced with void/nil.

Any function entries in a table passed in a remote event will also be removed.

I’d also like to say, you will have to replicate your client-sided functions if you want to make client-sided command execution.

It might be best to just clone a ModuleScript from ServerStorage to the client. You can parent the cloned ModuleScript into the PlayerGui so only that player receives the instance.

By the way, if sending the function via remote did work, then the client would have access to the admin script and could steal it anyways.

The best solution is for the server to check if you are an admin before sending anything. If this is true, then the server should send the guis, scripts, assets, etc. that you would get as an admin.

Also, do not use :InvokeClient(). A lot of things could break if you use it. Instead, you should have the client ask the server for the admin scripts and use :InvokeServer() instead.

The object being sent must not be in ServerScriptService or ServerStorage, as those are not available on the client.

I have never been able to send functions via remote functions / events, nor have I ever found this to be necessary. This is not currently possible: Ability to pass functions through remote events to client. Try one of the alternate methods of function wrapping instead (some are in the thread I’ve linked), or just design your system differently. Your current camera manipulation code is quite simple, although I’m sure you are making more sensitive commands. I’d argue that anything you don’t want to be accessed should NEVER be on the client anyways. If there was a way to send functions to a client, there would be a way to intercept said function and copy it before it is used. Never trust the client, so instead have your functions run server sided if they are that sensitive. Ui, player characters, and more can be easily edited server sided. I have no client sided admin commands, and any command dealing with lighting or camera sends arguments to predefined client functions through remote events. Changing lighting or camera settings is simple enough that no exploiter would waste time copying them.

Summarized: Sending functions is not necessary, edit what you can on the server and use predefined, simple functions for local camera and lighting changes. This level of extra protection is unnecessary, as anything on the client can be accessed, copied, and stolen with enough effort. I know that my ui and map can be stolen, but that is unfortunately not something I can change.

Thank you everyone for all of your comments, I decided to transfer any important information/need to know to a module script on the client, only containing the bare minimum of what it needs to execute the commands, but enough to make it work perfectly. Thank you for all of your replies. I greatly appreciate you guys putting your time and effort to help me out.