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:
- _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.
- 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:
- 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:
return {}
local list = require(game.ServerScriptService.ModuleScript)
table.insert(list, "hi")
wait(0.1)
local list = require(game.ServerScriptService.ModuleScript)
print(list[1])
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
local module = require(game.ServerScriptService.ModuleScript)
module.AddItem(3)
module.AddItem(5)
local module = require(game.ServerScriptService.ModuleScript)
wait(0.1)
print(module.GetSum())
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:
- 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
- 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.
- 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.
3 comments
I'd use RemoteEvents/RemoteFunctions
If I had a function that's used between multiple scripts I would just use a module
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?