Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

Script to script communication - Do I use _G.lobal functions?

Hi there,

I don't have a problem in particular, I am just curious what course of action I should take to have a script that can access another scripts' functions.

I have an Inventory script in every players StarterGUI (the script does create a GUI too so I put it here, is that an issue?). This script has a table for Items and a Items.new constructor that we'll assume I set up correctly. The Table simply records some basic information about the Item passed to it and will have another function later to "Retrieve" the item (which is essentially just ServerStorage:clone()'ing it).

The idea is that objects in the game world/workspace, like an apple for instance, can be clicked and one of their onClick functions is to delete itself from the world, and to create a new entity in the Items table. This would give the illusion of someone picking up the apple and putting it into their inventory.

Because of this, the apple's interaction script would need to access my Items.new constructor, located in a completely separate script and place.

Should I be using _G. (global)? or Shared[]? Should I use one of the above on the Items{} table? the Items.new function? or both? Do you have any general advice for what I am trying to do?

My only understanding of Classes comes from my limited experience in Java, so Lua classes/tables are a bit confusing to me.

Let me know if you need any more information! My actual code is pretty lengthy and unintuitive so I will only include it if you guys absolutely need to see what I am doing.

Thanks -Paco

3 comments

0

I'd use RemoteEvents/RemoteFunctions

0

If I had a function that's used between multiple scripts I would just use a module

0

Thanks! I haven't heard of either of these. Reading their descriptions in the API, I think Remote Events/Functions would be more appropriate than Module. Is there any advantage to using a module than a remote event for my goal?

1 answer

Hi! Welcome to Scripting Helpers.

You'll need to keep in mind that your scripts will be running in multiple real-world places -- one place is the server that Roblox provides (where server Scripts are executed) and the others are each of the players' machines (where the LocalScripts are executed), ie the clients. If you write code that you want to be able to run on both the server and each client, you'll need to put that code in a ModuleScript. If you want 2+ scripts to be able to communicate with each other and they are on the same machine, you have two options:

  1. _G. This is how scripts used to have to share data, but it's not advisable to use this -- in large projects, you're more likely to name two different things with the same name, causing data loss. It's also not great organization, unless you limit what you put in _G.
  2. BindableEvent/BindableFunction. I don't recommend using these (they will automatically delete non-integer keys in mixed tables that you send as arguments) when you can just use:
  3. ModuleScript. You can place functions, tables, and other variables inside a ModuleScript; they will only get evaluated the first time the ModuleScript is evaluated, meaning multiple scripts can refer to them. ex:
--ModuleScript acting as a global list of items, place it in game.ServerScriptService:
return {}
--Script 1:
local list = require(game.ServerScriptService.ModuleScript)
table.insert(list, "hi")
--Script 2
wait(0.1)
local list = require(game.ServerScriptService.ModuleScript)
print(list[1]) -- will print "hi"

--ModuleScript being more useful:
local list = {}
local sum = 0
local module = {}
function module.AddItem(item)
	table.insert(list, item)
	sum = sum + item
end
function module.GetSum()
	return sum
end
return module
--Script 1:
local module = require(game.ServerScriptService.ModuleScript)
module.AddItem(3)
module.AddItem(5)
--Script 2:
local module = require(game.ServerScriptService.ModuleScript)
wait(0.1)
print(module.GetSum()) -- 8

If you need the client to communicate something to the server (or vice versa), you have to use RemoteEvents/RemoteFunctions. (If you aren't using FilteringEnabled (not recommended), you can often have the client just make the adjustment to the game world directly, but this lets players mess up your game world in any way they like, ruining the game for everyone. Note that exploiting can still occur, but it's not nearly as damaging.)

So, in your case, you might have these scripts/functions:

  • Inventory ModuleScript in ReplicatedStorage (so that it can be accessed by everyone -- you could also put it in Workspace, just have an organization strategy and be consistent). This script could contain things like Item.new, or just manage player inventory. Note that if you want your game to be secure, the inventory has to be managed by the server -- otherwise, a theoretical exploiter (even with FilteringEnabled) would be able to tell your server that they have whatever inventory they choose. If the Inventory script is not needed at all by the client, you can put it in ServerScriptService or ServerStorage instead.
  • InventoryGui script in StarterGui (it should stick to managing the GUI and collecting user input and sending the meaning of that input to the server)
  • RemoteEvents to let your Inventory server script let your InventoryGui script what inventory the player has when they load in and what inventory they gain over time
  • RemoteEvent/Function for your Gui script to let the server know when the player wants to use/drop/whatever an item (the server should not trust the client but should make sure that the player actually has the item before acting on it)

If the user clicks on an apple in the world, the proper information flow should be something like this:

  1. Some LocalScript takes note of the click (through the GUI you have set up for it) and uses a RemoteFunction to ask the server for permission to pick it up
  2. The server makes sure that the item (still) exists [ex another player could have picked it up first, or the player is an exploiter inventing items out of nowhere]. If so, it deletes the apple from the world, stores the apple in the player's inventory (server-side), triggers an event that the player now has an apple in their inventory, and returns true.
  3. If the LocalScript receives "false", it might tell the user "The item has disappeared!" or "Something went wrong". Otherwise, it probably does nothing, but could also tell the user "You picked up an apple" (possibly, such notifications should be part of the event the server triggers).

By the way, if your code is unintuitive, something might be wrong. The ideal code is reasonably straightforward to read (making it easy to understand after you've forgotten what it does and also allowing easy debugging/changing) -- code rarely starts out this way, but ideally you try to improve it before it gets too far out of hand (not as important if you're just trying things out for fun, of course). Some important ones are DRY (Don't Repeat Yourself) and SOLID (which is actually 5 guidelines, but the 'S' is "Single Responsibility Principle" -- each class should be responsible for one thing, not tons of things. Practically, don't strive for exactly "one thing" so much as "as few as possible" -- if you can split it up into a couple smaller classes without making the code complicated, it might be a good idea to do so.) On the other hand, if this is a learning project, some people have found that disregarding the principles/guidelines may help you learn why they're valuable.

"My only understanding of Classes comes from my limited experience in Java, so Lua classes/tables are a bit confusing to me." If my explanations are doing you any good, I'd be happy to help you out more. If so, you could contact me at chess123mate@yahoo.ca , add me on Skype (same email), or add me on Steam (chess123mate). Let me know via email or by replying to this Answer if you intend to add me (and with what username I'll recognize you) so I know it's not a bot. Alternatively, simply make a new Question expressing what you're confused by and link me to it (via comment to this Answer) and I'll see what I can do.

This discussion is preserved as it was. New answers, comments, and votes are closed.