Plugin config
Declare typed config in package.json under s2script.config. The host materializes defaults ⊕ an admin-editable JSON override at load.
{
"s2script": {
"config": {
"greeting": { "type": "string", "default": "hello", "description": "Chat greeting" },
"max_uses": { "type": "int", "default": 3 },
"cooldown": { "type": "float", "default": 0.75 },
"enabled": { "type": "bool", "default": true }
}
}
}Supported types: string, int, float, bool. Wrong-typed override values degrade to the default and log a warning — never crash.
Each declaration takes these fields. s2s build rejects a block that breaks the rules.
| Field | Applies to | Meaning |
|---|---|---|
type | all | string, int, float or bool. Required. |
default | all | Required, and must match type. |
min / max | int, float | Bounds the default must sit within. Not combined with enum. |
enum | string, int | Non-empty list of allowed values; the default must be one of them. |
description | all | Shown in the generated file and on the package page. |
label | all | Short display name for the package page. |
group | all | Package-page heading the option is listed under. |
sensitive | all | true hides the default on the package page. The file still gets it. |
An object without a string type is a section: its keys are further declarations, read with dotted names such as config.getString('chat.prefix'). Keys may not contain ..
Reading values#
Read through the config object — a plain named import, valid anywhere in your plugin:
import { config } from '@s2script/sdk';
export function OnPluginStart(): void {
const greeting = config.getString('greeting');
const maxUses = config.getInt('max_uses');
const cooldown = config.getFloat('cooldown');
const enabled = config.getBool('enabled');
}Undeclared keys return the type’s zero value (empty string / 0 / false), never throw.
Live reload#
Opt in by subscribing on config — the first onChange starts watching the override file. Edits re-materialize and fire handlers without reloading the plugin:
import { config } from '@s2script/sdk';
export function OnPluginStart(): void {
config.onChange(() => {
console.log('config changed → greeting =', config.getString('greeting'));
});
}config.onChange is not load-window-gated. No subscriber → config is read once at load (zero watch overhead).
Raw files#
config.readFile / config.writeFile read and write plain files under addons/s2script/configs/ (e.g. maplist.txt) — the name includes its extension, and traversal is rejected.
Override files themselves live at addons/s2script/configs/<plugin-id>.json and are auto-generated on first load with defaults and // comments.
See the config module.
Host process limits#
Plugin s2script.config is not the host process budget. Operators set S2SCRIPT_ASYNC_LIMITS_JSON on the game process before start (JSON object, any subset of fields; unknown or invalid values fall back to full defaults and a warning). The policy is read once per process. Field table, defaults, and __s2_async_stats are on Async & networking.