Hello, this is my first post on the DevForum, hello.
Recently I’ve attempted to use a one script architecture with module scripts because I found it to be a great way to organise my project, but there’s barely any documentation on this whole thing and I am not sure if I am doing it correctly.
--[[
The server initializer script used to get all the server-side modules
--]]
local modules = {} -- the modules table, where all the modulescripts are stored
-- Looping through the scripts descendants searching for moduleScripts, if moduleScript then add it to the table by requiring it,
for i,obj in pairs(script:GetDescendants()) do
if obj.ClassName == "ModuleScript" then
modules[obj.Name] = require(obj)
end
end
for i,obj in pairs(game:GetService("ReplicatedStorage").Modules.Shared:GetChildren()) do
if obj.ClassName == "ModuleScript" then
modules[obj.Name] = require(obj)
end
end
-- Initialise all ModuleScripts by calling its init() function which should be in every module script
for name,module in pairs(modules) do
if module["init"] then
module.init(modules)
end
end
So basically I have a Script and a LocalScript which require all of their respective side’s modules + shared modules and put them in a table. (shared modules means both for server and client)
Then the Script / LocalScript initialises all of the ModuleScripts by looping through them and calling their init() function which passes the modules table as a paramater so the modules have access to the other modules just by reference.
Notice how the Script and LocalScript do the same thing just requiring server-sided modules and client-sided modules respectively.
I could accomplish the same thing by using a Main ModuleScript which would have an init() function which would do the same thing but check if it’s client or server and then add the modules to that respectively. Like;
local main = {}
function main.init()
local group
local modules = {}
if not game.Players.LocalPlayer then
-- server
group = game.ServerScriptService.Modules.Server
else
group = game.ReplicatedStorage.Modules.Client
end
for i,obj in pairs(group:GetChildren()) do
if obj.Name == "ModuleScript" and obj.Name ~= script.Name then
modules[obj.Name] = require(obj)
end
end
for i,obj in pairs(game.ReplicatedStorage.Modules.Shared:GetChildren()) do
if obj.Name == "ModuleScript" and obj.Name ~= script.Name then
modules[obj.Name] = require(obj)
end
end
for name,module in pairs(modules) do
if module["init"] then
module.init(modules)
end
end
end
return main
and then the Script and LocalScript would require that main module.
Also, how about loading screens? Putting a module under ReplicatedFirst would take out the purpose of ReplicatedFirst as it would have to wait for the LocalScript to res in and call the module, because modules dont run instantly, so the most optimal solution would probably be to create a LocalScript for loading screens instead, or have a loading screen inside of StarterGui.
Should I use a Main Module Script for initialising and then let the other scripts require the main module or should I let the other scripts do the initialising work?
(aka should I use the former or the latter)
Let me know what you think of this system, what you think of how I implemented it,and what should be improved.