- This code takes a look at all modules in a folder called “Modules” inside ServerScriptService and runs .init() and .start() functions on them (every .init() function should run before any of the .start() functions run).
- I have two main concerns with my current code, and I’m not sure if I should be too worried about them or not:
-
- Are coroutines outdated because of the task.spawn() system? And if so, how can I replace current portions of my code with it?
-
- The code seems very repetitive in certain parts, and I’m not sure if there’s a way to take up less space while maintaining readability.
Thanks for any feedback,
- P_rceptionNull (Noxira)
--!strict
--[[
SERVER-SIDED MODULE LOADER:
- requires all modules in Server Script Service's module folder
- runs init() asynchronously on the modules, expects a returned true value
- runs run() asynchronously on the modules, expects a returned true value
]]
--------------
-- SERVICES --
--------------
local ServerScriptService = game:GetService("ServerScriptService")
-----------
-- TYPES --
-----------
type RequiredModule = {
["init"]: () -> boolean, -- runs first, used for connections (DO NOT STORE DEPENDENCIES IN HERE)
["start"]: () -> boolean, -- runs after .init(), used for starting systems
[string]: () -> any? -- for any public functions/methods that other modules may want to access
}
---------------
-- CONSTANTS --
---------------
local modulesFolder = ServerScriptService.Modules
---------------
-- VARIABLES --
---------------
local successfullyInitializedModules: { ModuleScript } = {} -- modules that returned true on .init()
---------------
-- FUNCTIONS --
---------------
-- Runs .init() on all modules and saves the ones that returned true on .init() to successfullyInitializedModules array.
local function initModule(requiredModule: RequiredModule, module: ModuleScript)
if typeof(requiredModule.init) ~= "function" then -- verify init function exists
error("[SERVER]: Module " .. module.Name .. " missing .init().")
end
local thread = coroutine.create(requiredModule.init) -- allow for asynchronous execution
local success, result = coroutine.resume(thread)
if not success then -- check for error in resuming coroutine
error("[SERVER]: Coroutine failed for module: " .. module.Name .. ".")
end
if result then -- returned true, things are good
print("[SERVER]: Successfully initialized module: " .. module.Name .. ".")
table.insert(successfullyInitializedModules, module)
else -- failed to return true
warn("[SERVER]: Failed to initialize module: " .. module.Name .. ".")
end
end
-- Runs .start() on all modules that were saved on successfullyInitializedModules array.
local function runModule(module: ModuleScript)
local success, requiredModuleToStart: RequiredModule = pcall(require, module) -- make sure no issues when requiring
if not success then
error("[SERVER]: Error requiring module: " .. module.Name .. ".")
end
if typeof(requiredModuleToStart.start) ~= "function" then -- verify start function exists
error("[SERVER]: Module " .. module.Name .. " missing .start().")
end
local thread = coroutine.create(requiredModuleToStart.start) -- allow for asynchronous execution
local success, result = coroutine.resume(thread)
if not success then -- check for error in resuming coroutine
error("[SERVER]: Coroutine failed for module: " .. module.Name .. ".")
end
if result then -- returned true, things are good
print("[SERVER]: Successfully started module: " .. module.Name .. ".")
else -- failed to return true
warn("[SERVER]: Failed to start module: " .. module.Name .. ".")
end
end
-- Runs .init() on all module-scripts and runs .start() after they have all been initialized
local function run()
for _, moduleToInit: ModuleScript in ipairs(modulesFolder:GetChildren()) do
if not moduleToInit:IsA("ModuleScript") then -- verify things in module folder are modules
continue
end
local success, requiredModule: RequiredModule = pcall(require, moduleToInit) -- make sure no issues when requiring
if not success then
error("[SERVER]: Error requiring module: " .. moduleToInit.Name .. ".")
end
initModule(requiredModule, moduleToInit) -- run the init, shouldnt hold up the thread
end
for _, moduleToStart: ModuleScript in ipairs(successfullyInitializedModules) do
if not moduleToStart:IsA("ModuleScript") then -- makes sure array elements are modules
continue
end
runModule(moduleToStart) -- run the start function, shouldnt hold up the thread
end
end
-------------
-- BINDING --
-------------
-------------
-- RUNNING --
-------------
run() -- get things started
ServerSidedModuleLoader.rbxm (3.3 KB)