mods
Registry of mods whose scripts executed without throwing.
api.mods. 2 members. The loader registers a mod after its script returns, so a mod is absent during its own script, and mods later in load order are absent until their scripts run. Hot reload empties the registry before the scripts re-execute.
| Member | Returns | Summary |
|---|---|---|
isLoaded(modId) | boolean | Whether a mod id is in the loaded-mod registry. |
getLoadedMods() | LoadedModInfo[] | A copy of every loaded mod's registry entry. |
isLoaded#
api.mods.isLoaded(modId: string): booleanWhether a mod id is in the loaded-mod registry.
A mod enters the registry after its script finishes without throwing. Disabled mods, mods with manifest errors and mods whose script threw are absent. During a mod's own script execution its own id is not yet registered.
Parameter modId (string): the id from the other mod's manifest.
Returns: boolean. true when registered; false otherwise, including when the lookup throws.
// optional integration with another mod
if (api.mods.isLoaded('com.example.better-fares')) {
console.log('Better Fares found: skipping our own fare tweaks');
}getLoadedMods#
api.mods.getLoadedMods(): LoadedModInfo[]A copy of every loaded mod's registry entry.
Entries are added in load order after each script finishes without throwing.
Returns: LoadedModInfo[]. Array of fresh LoadedModInfo copies (editing them changes nothing); an empty array when the lookup throws.
for (const mod of api.mods.getLoadedMods()) {
console.log(`${mod.name} ${mod.version} by ${mod.author} (${mod.id})`);
}LoadedModInfo#
Registry entry for a loaded mod, copied from its scanned manifest.
The loader fills id, name and version from the manifest and author from author.name.
| Field | Type | Default | Description |
|---|---|---|---|
id | string | required | Manifest id; the key used by storage and by mods.isLoaded. |
name | string | required | Manifest name, the display name. |
version | string | required | Manifest version. |
author | string | none | Manifest author.name. Unknown when the manifest's author is missing or falsy (the scanner substitutes { name: 'Unknown' }); undefined when author is present but is not an object with name. |
Load Order#
At startup the loader lists the folders in the mods directory, keeps the mods that are enabled and have a valid manifest, and runs their scripts one after another in directory listing order. The order is not configurable, and no manifest field declares dependencies.
A mod enters the mods registry only after its script returns without throwing. So at the top of a script, mods that ran earlier are visible and mods that run later are not, and a mod never sees its own id. Check for a dependency inside a hook instead. onGameInit fires only for new games, so also use onGameLoaded to cover save loads:
const checkDependency = () => {
if (!api.mods.isLoaded('transit-data-core')) {
api.ui.showNotification('This mod needs Transit Data Core.', 'warning');
}
};
api.hooks.onGameInit(checkDependency);
api.hooks.onGameLoaded(checkDependency);Hot reload (reloadMods) empties the registry and runs the scripts again in the same order.
Communicating Between Mods#
The API has no message channel between mods. Every script runs in the same page, wrapped in its own function scope, so a namespaced property on window is the simplest shared channel:
// Provider mod
window.MyStatsMod = {
version: '1.0.0',
getDailyRidership: () => api.gameState.getRidershipStats().totalRiders,
};
// Consumer mod, inside a hook so the provider has loaded
api.hooks.onGameInit(() => {
if (api.mods.isLoaded('my-stats-mod') && window.MyStatsMod) {
console.log(window.MyStatsMod.getDailyRidership());
}
});storage is not a shared channel: while a mod's script or hook callback runs, calls use that mod's own file and ignore an explicit modId.