Calling ModuleScript functions from the client

So I have some functions in a ModuleScript that are called by the client, but that I need to run server-side. The first solution I came up with was a RemoteFunction accompanied by a script in ServerScriptService:

local RemoteFunction = game.ReplicatedStorage:WaitForChild("ModuleCaller")
RemoteFunction.OnServerInvoke = function(moduleFunction, ...)
	if ... == nil then
		moduleFunction()
		return nil
	else
		return moduleFunction(...)
	end
end

The intention of this was to allow the RemoteFunction to be called from the client with the function it wanted to run (and the module, i.e. Module.Function(parameter)) and then run that function (the if … == nil thing was to allow functions without parameters to use the same system)

This doesn’t work, with the error ‘attempt to call a Instance value’ appearing both in line 4 of the above and the local script I invoked the function from.

Therefore, how could I efficiently have a module function called by the client run server-side, or fix the above?

When OnServerInvoke fires, it passed the player object as the first argument so you need to change function(moduleFunction, ...) to something like function(_,moduleFunction, ...) so you actually fire the function you passed with :InvokeServer().

1 Like

Did that - it now errors with ‘attempt to call a nil value’ i.e. moduleFunction is nil. This happens when I pass both Module.Function and Module.Function() as that parameter.

Try making a RemoteFunction for each one instead. Or you could pass the name of the function, which
would be a bit closer to your current design.

1 Like

The first argument that is passed to OnServerInvoke is the player. Change line 2 of your code to accommodate for this.

As in, one RemoteFunction per function? My issue with that is that it’s clunky and would take forever to do. And can you explain what you mean by the latter?

Something like:

-- ...
if module[funcName]  then
  return  module[funcName]( ... )
end
2 Likes

I have a feeling what you’re trying to do is reliant on the client and server sharing the same memory which isn’t the case. You can’t pass any function directly from the client to the server so you’d have to try and change this to a reference based system.

2 Likes

The latter method that was suggested is having the server script also load the module and then have the client invoke the remote function and send the name of the function as an argument instead of the function itself.

(Very similar to what @Club_Moo wrote) something like:

local module = require(\path)

remoteFunction.OnServerInvoke = function(player, funcName, ...)
    if module[funcName] then
        return module[funcName](...)
    end
end
3 Likes