Module Scripts from Local And Server

Hello! I am becoming more and more familiar with modules… Finally! But, i have a very important question that i cant seem to find a straight answer for: If you call a module from a local script, will it only perform the function in the client? Or can it run in the server? and if so, how?

Now, What is the cleanest way of bouncing a modular function back and forth from local and server functions? For instance, if i want to call a server function from a module, in a local script, would i need to remote to a server and then perform the function? If so, then what is the point of using a module instead of just a server script?

I am cleaning up a very messy magical system for my game, ’ A Mystical Life’, and i want it to be primarily modular… however it requires stuff from both local and server so i’m wondering what the best way of doing this is. The functions themselves aren’t important… I can figure that stuff out, whats important is me understanding the relationship of modules between server and client. THANKS! :slight_smile:

11 Likes

loading a ModuleScript is kinda like calling a bindablefunction, the code will act like it is the localscript, that means that, no, the localscript cannot do any server-only function

1 Like

Okay! Thanks thats helpful. And im assuming then that if called by the server, then it cant do anything in the local player like tweening a gui?

1 Like

Yes, that’s correct, imagine requiring a modulescript as asking for it’s code to be ran inside the script!

1 Like

Any strategies on bouncing around the locals and sever scripts for the modules?

If i am correct mutliple scripts can require the same module

Like for making it more practical other than just bouncing around with remote events and what not.

That would be harder, i think your only option is remote events.

Alright thanks so much for your quick responses! :slight_smile:

1 Like

No problem, remember if you come up with a way to bounce around, you can always use RunService:IsClient() and RunService:IsServer() to get if the code is running in the client or in the server!
If you think your question got solved, don’t forget to mark as solved!

5 Likes

Also, if the module script is in replicated storage then you can require it from both a local script and script.

1 Like

A ModuleScript is basically a Local Script and a Server Script at the same time. When you require a ModuleScript, you’re doing that through either the Client or the Server. When you execute code through that ModuleScript, either the Client or Server will run that code.
As an example, if I had function foo() in a ModuleScript (game.Workspace.Module), On my Client, I’d do:

local module = require(game.Workspace.Module)

When I did module.foo() the Client would run that code. If I did it from a Server script, the Server would execute that function.

If you’re looking for communication across the Client-Server boundary, Look into RemoteEvents and RemoteFunctions.

If you’re looking to learn about ModuleScripts, there are tons of tutorials on YouTube that are step by step guides.

Edit: You can also use a RemoteEvent to tell the Client to execute a function in a ModuleScript if needed.

11 Likes

Not exactly, there are a few differences.

From what I remember, module scripts will cache the result that is returned.
i.e

--in the script
require(script.ModuleScript)
require(script.ModuleScript)
--in module script under the script
print(1)
return nil

This will only print once, as the result is cached and the module script won’t run again when the require function is called on it.

But using a BindableFunction the result isn’t cached.
i.e

local Bind = Instance.new"BindableFunction"
function Bind.OnInvoke()
	print(1)
	return nil
end
Bind:Invoke()
Bind:Invoke()

This will print out twice, as the data isn’t cached.

Also, logically using a BindableFunction could have issues as the script which registers the function should run before all the functions which use it. (if its not registered then it will yield until a function is registered, but its still an unnecessary yield) Module scripts don’t suffer from the issue because they don’t need any script to register the function.

3 Likes

Thankyou! Yes, i’m familiar with remote events and functions, i just want to downsize the amount of running scripts as possible :slight_smile: so i’m moving to modules.

In addition, what I do for my game when I need for modules to be use with both server and client alot is by using the run service for example:

local RunService = game:GetService("RunService")
module.Example = function()
    if RunService:IsClient() then
             --This will check if the module is running on the client
    elseif RunService:IsServer() then
            --This will check if the module is running on the server
   end
end

This way you can have the client and server call the same module, but will carry out different instructions and its pretty neat and I ended going from using 5 remotes for one task to none through manipulating this tactic.

6 Likes

You can check where is has been required from with RunService:IsClient(), which returns true on the client and false on the server. Then, just use remotes on the client version and connect them on the server side one, and you should be good.

1 Like

If the information I provided is what you were looking for, make sure to mark it as the solution so others can see it when they come across your post.

If the ModuleScrips functions are being ran by a LocalScript they will only be ran on the client. If the ModuleScripts functions are being ran by a script then they will only be ran on the server.

I am going to try and explain this as best as I can so bare with me. A ModuleScript is a container where you store code until it is required. This means you can run functions that are in a module in multiple scripts at the same time.

If your ModuleScript is located within ReplicatedStorage you can require it from the server and the client. This means you can run the functions in the ModuleScript on the client and the server at the same time. However if you change any variables/tables ect on the client they wont be replicated to the server and vice versa.

Instead of using the same function and changing it’s action based on the environment, it would be much easier to change the function itself based on the environment. I find this to be much more manageable.

local RunService = game:GetService("RunService")

local IS_SERVER = RunService:IsServer()

local module = {}

module.Example = IS_SERVER and function(args)
    print("server", args)
end or function(args)
    print("client", args)
end
7 Likes