Init
A module loader for Roblox games. You point Init at folders, and it requires every module in
them in a fixed order, calls their Init and Start methods, and wires up the methods you
would otherwise connect by hand (OnPlayerAdded, OnHeartbeat, OnCharacterAdded, ...).
One Script on the server and one LocalScript on the client boot the whole game:
-- ServerScriptService/InitServer (Script)
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local Init = require(ReplicatedStorage.Packages.Init)
Init.start({
{ Folders = { ReplicatedStorage.Network } },
{ Folders = { ReplicatedStorage.Services, ServerScriptService.Services }, Predicate = Init.matchesName("Service$") },
{ Folders = { ReplicatedStorage.Binders.Shared, ServerScriptService.Binders } },
})
A module Init loads is a plain table. Every method is optional:
local PointsService = {}
function PointsService.Init(self: PointsService)
self.Points = {} -- set up your own state; don't wait for other modules here
end
function PointsService.Start(self: PointsService)
-- every module has finished Init, so it's safe to use them
end
function PointsService.OnPlayerAdded(self: PointsService, player: Player)
self.Points[player] = 0
end
return PointsService
See the lifecycle for the exact order things run in.
Types
Settings
Every option with its default lives in
Settings.luau and on the
settings page.
Entry
interface Entry {Predicate: ((module: ModuleScript) → boolean)?--
only load modules this returns true for, e.g. Init.matchesName
Order: number?--
only used when entries are a dictionary (the old Entries-module format): lower runs first
}
One group of modules to load. A ModuleScript inside another ModuleScript is never loaded on its
own: it belongs to its parent, which can require it.
Entries
A list of entries, loaded in list order. A dictionary of named entries (the format of the old
SharedEntries/ServerEntries modules) also works and is sorted by each entry's Order.
Modules
type Modules = {[string]: any}Every loaded module's returned value, by the ModuleScript's name.
Functions
start
This is a yielding function. When called, it will pause the Lua thread that called the function until a result is ready to be returned, without interrupting other scripts. YieldsLoads and starts every module the entries point at. Call it once per realm: from one Script on the server and one LocalScript on the client.
-
Load: requires the modules, entry by entry. Inside an entry, modules with a lower
Priorityattribute go first. Modules with anIgnoreattribute, modules a Predicate turns down and ModuleScripts that sit inside another ModuleScript are skipped. -
Init: calls
Initon each module, one at a time, in load order. If one errors or takes longer thanInitTimeout, it's reported and that module won't Start. -
Start: calls
Starton every module at once (a Start that waits doesn't hold up the others). Each module's hooks (OnPlayerAdded,OnHeartbeat, ...) connect as soon as its own Start returns.
The returned promise resolves after every Start has returned (or hit StartTimeout), with the
loaded modules by name, how many loaded, and how long it took in seconds.
Init.start(entries):andThen(function(modules, count, seconds)
workspace:SetAttribute("ServerStarted", true)
end)
matchesName
Makes a Predicate that keeps modules whose name matches a string pattern.
{ Folders = { ServerScriptService.Services }, Predicate = Init.matchesName("Service$") } -- names ending in Service