Registry
local Operator = require(game:GetService("ServerStorage").Operator)
local Registry = Operator.RegistryHolds the commands and argument types a server knows about. Operator.Start builds one for you and exposes it as handle.registry.
Functions
Registry.new
Registry.new(): RegistryStarts with all nine built-in types already registered.
Methods
:registerType
registry:registerType(argType: AnyArgType): ()Registers one argument type. Types referenced by a command are registered automatically, so this is only needed for a type no command mentions yet.
Registering a different type under a name already taken is a loud error rather than a silent overwrite.
:registerCommand
registry:registerCommand(command: Command): ()Registers one command. Commands registered after Start work normally, and the next refresh puts them in the manifest.
:LoadTypesIn
registry:LoadTypesIn(container: Instance): numberRequires every ModuleScript below container as an argument type. Returns how many were registered.
:LoadCommandsIn
registry:LoadCommandsIn(container: Instance): numberRequires every ModuleScript below container as a command. Returns how many were registered. Each module must return a command, or an array of commands.
Both loaders scan all descendants, so grouping command files into subfolders works.
Loading is all-or-nothing
If any module fails to require, returns the wrong shape, collides with an already-registered path, or collides with another module in the same load, nothing is registered and the error names every offending module.
A half-registered console, a command present on some sessions and missing on others, is exactly the failure this prevents.
:LoadClientCommandsIn
registry:LoadClientCommandsIn(container: Instance): numberRequires every ModuleScript below container as a client command. Returns how many were registered.
Unlike LoadCommandsIn, each module must return function(Command, Types) rather than the command itself, because a client command module is required on both the server and the client and cannot hardcode a path that resolves in both places.
A module here that uses :run() instead of :runClient() is a load error naming the file, and the reverse is true of LoadCommandsIn.
:getType
registry:getType(name: string): AnyArgType?Looks up a type by name, case-insensitively.
:getTypes
registry:getTypes(): { AnyArgType }:getCommand
registry:getCommand(path: { string } | string): Command?Looks up a command by "admin ban" or { "admin", "ban" }, case-insensitively.
:getCommands
registry:getCommands(): { Command }Example
local registry = Registry.new()
registry:LoadTypesIn(script.Parent.Types)
local count = registry:LoadCommandsIn(script.Parent.Commands)
print(`registered {count} commands`)