Module structure
Modules live in the mods directory at the Toolbox root. A regular module occupies its own folder. The legacy standalone format is a single .js file with limited capabilities; use a folder with module.json for new development.
mods/
hello-toolbox/
module.json
index.js
Toolbox loads the entry point with require(moduleFolder): normally index.js, or another file selected by main in package.json. Toolbox metadata belongs in module.json, not package.json. An automatically updated module also needs manifest.json.
Your first module
Create module.json:
{
"name": "hello-toolbox",
"author": "Your name",
"description": "A minimal Toolbox module",
"disableAutoUpdate": true
}
Create index.js:
module.exports = function HelloToolbox(mod) {
const onEnter = () => mod.log(`Hello, ${mod.game.me.name}!`);
mod.game.on('enter_game', onEnter);
mod.command.add('hello', () => mod.command.message('Hello from Toolbox!'));
this.destructor = () => {
mod.game.removeListener('enter_game', onEnter);
};
};
Restart Toolbox and connect to the server through it. Entering the game logs a greeting; the hello command replies in game through the command module. Disabling automatic updates during development prevents remote files from replacing local changes.
Exports and lifecycle
A class can also be the entry point:
module.exports.NetworkMod = class Example {
constructor(mod) {
this.mod = mod;
mod.log('Module loaded');
}
destructor() {
this.mod.log('Module unloaded');
}
};
| Export | Lifetime |
|---|---|
GlobalMod |
One instance for the loaded module |
ClientMod |
An instance per connected client interface |
NetworkMod |
An instance per game network connection |
RequireInterface |
The interface exposed to dependent modules |
A plain function or class export is supported through a compatibility wrapper. Named exports separate client, network and shared logic. Avoid module-level variables for state that must remain independent between game connections.
Toolbox calls the optional destructor() when unloading an instance. Framework hooks, commands and managed timers are cleaned up automatically; remove your own listeners on shared emitters, windows and other resources yourself. Constructors cannot be asynchronous: start asynchronous work from an appropriate event and handle errors.
Next steps
Read metadata and updates, hooks and game state. Network modules handle packets; client modules can install resource files. These are different API scopes.
Sources: doc/mod/main.md, bin/mod.js, bin/mod-legacy-wrapper.js.