Settings schema (GenerateConfig)

Call GenerateConfig([...]) at addon load time to declare settings fields. Schemas are stored in app config; values live in addonsParams[id]. Defaults are merged on registration and when the settings page opens.

Field structure

Each field has:

Property Description
key Storage key in params object
type text, textarea, hidden, color, number, boolean, array, object, select, choice, button, folder, file, info, spoiler, page
pathPicker For folder / file: title, filters (file only), filename (exact basename), namePattern (regex on basename, file only)
default Initial value
editor If present, field appears in settings UI with label, validation, etc.
options For select / choice: { value, label?, description? }[]
visibleWhen Optional { key, equals } — hide the field unless params[key] === equals
items For array: 'text' or 'number'. For spoiler / page: nested schema entries (same shape as GenerateConfig arguments; recursion allowed)
fields For object: nested fields
event For button: event name fired on click (handle with events.On)

Fields without editor are persisted (internal counters, tokens) but not shown in the UI.

Inline rows

Wrap multiple fields in a nested array to render them on one settings row:

GenerateConfig([
  fieldA,
  [fieldB, fieldC],
  fieldD,
]);

Supported types

Nested fields inside spoiler / page store values at the parent params level (sibling keys to the container), not under the container key.

Optional visibleWhen: { key, equals } hides a field in the settings UI unless the sibling params value matches (useful for custom-only fields).

Spoiler / page example

{
  key: 'advanced',
  type: 'spoiler',
  editor: {
    label: { en: 'Advanced', ru: 'Дополнительно', uk: 'Додатково' },
    description: { en: 'Optional tuning' },
  },
  items: [
    {
      key: 'debug',
      type: 'boolean',
      default: false,
      editor: { label: { en: 'Debug logging' } },
    },
    {
      key: 'network',
      type: 'page',
      editor: { label: { en: 'Network' } },
      items: [
        {
          key: 'timeout_ms',
          type: 'number',
          default: 5000,
          editor: { label: { en: 'Timeout (ms)' } },
        },
      ],
    },
  ],
},

Info block example

{
  key: 'mod_warning',
  type: 'info',
  editor: {
    label: { en: 'Important' },
    description: {
      en: 'This mod may trigger anti-cheat on some servers. Use at your own risk.',
    },
    infoBorder: 'yellow',
  },
},

Path picker UI

folder and file fields render as a non-editable path field with Browse and Open actions. Open stays disabled until a path is chosen. For files, Open reveals the file in the system file manager.

Example

GenerateConfig([
  {
    key: 'api_server',
    type: 'text',
    default: 'https://example.com:2083',
    editor: {
      label: { en: 'API server', ru: 'API сервер', uk: 'API сервер' },
    },
  },
  {
    key: 'theme',
    type: 'select',
    default: 'dark',
    options: [
      { value: 'dark', label: { en: 'Dark', ru: 'Тёмная', uk: 'Темна' } },
      { value: 'light', label: { en: 'Light', ru: 'Светлая', uk: 'Світла' } },
    ],
    editor: { label: { en: 'Theme', ru: 'Тема', uk: 'Тема' } },
  },
  { key: 'last_sync', type: 'number', default: 0 },
  {
    key: 'reconnect',
    type: 'button',
    event: 'onReconnect',
    editor: { label: { en: 'Reconnect', ru: 'Переподключиться', uk: 'Перепідключитися' } },
  },
]);

events.On('onReconnect', async () => {
  // user clicked Reconnect in settings
});

Reading params

const params = await api.config.getParams();
await api.config.updateParams({ last_sync: Date.now() });

Size limit: 10 000 bytes JSON per addon unless INCREASE_CONFIG_SIZE is granted (1 000 000 bytes).