Plugin settings
How settings work
A plugin's settings live in an ordinary AzerothCore module config. Two files describe them:
| File | Read by | Purpose |
|---|---|---|
conf/<name>.conf.dist |
the server | The options, their defaults and comments. Named by config in plugin.json. |
settings.json |
the launcher | Which of those options the Settings tab shows, with labels, types and limits. |
The launcher never talks to your code. It writes values into the plugin's config file; the server reads that file
through its config manager. A plugin without config gets no Settings group, whatever its settings.json says.
This guide extends the example.greeter plugin from Your first plugin. The full field
reference is Launcher settings.
1. Add the config
conf/greeter.conf.dist:
#
# example.greeter
#
[worldserver]
#
# Greeter.Enable
# Description: Greet players when they log in.
# Default: 1 - (Enabled)
# 0 - (Disabled)
#
Greeter.Enable = 1
#
# Greeter.Message
# Description: The text sent on login.
# Default: "Welcome to the server!"
#
Greeter.Message = "Welcome to the server!"
and name it in plugin.json:
"config": "conf/greeter.conf.dist"
AddPlugin copies the conf folder into the laid-out plugin. The config's name is the file name without .dist:
greeter.conf.
2. Read the values
#include "Chat.h"
#include "Config.h"
#include "Player.h"
#include "ScriptMgr.h"
class GreeterPlayerScript : public PlayerScript
{
public:
GreeterPlayerScript() : PlayerScript("GreeterPlayerScript", { PLAYERHOOK_ON_LOGIN }) { }
void OnPlayerLogin(Player* player) override
{
if (!sConfigMgr->GetOption<bool>("Greeter.Enable", true))
return;
ChatHandler(player->GetSession()).SendSysMessage(
sConfigMgr->GetOption<std::string>("Greeter.Message", "Welcome to the server!"));
}
};
Where the values come from, later sources winning:
- the
.distin the plugin folder, which declares every option; modules/greeter.confbeside the config the server was started with (-c), when it exists, key by key: a key it leaves out keeps the.distvalue. In a LonelyIce server folder that isconfigs/modules/greeter.conf. Only when there is nomodulesfolder beside the config does the core look in its default config directory;- an environment variable
AC_<KEY>(Greeter.MessagebecomesAC_GREETER_MESSAGE), fixed when the server process starts.
A plain worldserver of the fork reads the same files; nothing here needs the launcher. reload config reads 1 and 2
again; 3 still wins afterwards.
3. Describe the Settings group
settings.json next to plugin.json:
{
"group": { "en": "Greeter", "ru": "Приветствие" },
"hint": { "en": "What players see when they log in", "ru": "Что видят игроки при входе" },
"fields": [
{ "key": "Greeter.Enable", "type": "bool", "apply": "reload",
"label": { "en": "Greet on login", "ru": "Приветствовать при входе" } },
{ "key": "Greeter.Message", "type": "string", "apply": "reload",
"label": { "en": "Message", "ru": "Сообщение" },
"hint": { "en": "Sent as a system message", "ru": "Отправляется системным сообщением" } }
]
}
The launcher finds settings.json in the plugin folder by itself. "settings" in plugin.json can instead name
another file or hold the same object inline. A bare array of fields is also accepted; the group is then named after
the plugin and its hint is the plugin's description.
The group appears in the Settings tab under Plugins, sorted by group name. On the Plugins page the plugin gets a gear button that opens it.
Field types
type |
Control | Written to the config |
|---|---|---|
bool |
checkbox | In the style the file already uses for that key: 1/0, true/false or yes/no. |
int |
number field | Parsed, clamped to min/max, rounded to an integer. A value that is not a number is refused. |
float |
number field | Clamped to min/max when either is given; otherwise written as typed. |
string |
text field | As typed. |
choice |
drop-down of options |
The chosen option's value. |
Other keys of a field:
| Key | Meaning |
|---|---|
key |
The config option. Required. |
label, hint |
Localized strings (an object of language → text, or a plain string). label defaults to the key. |
min, max |
Numbers, for int and float. |
options |
For choice: [ { "value": "0", "label": { "en": "Off" } }, ... ]. Values may be written as numbers or strings. |
default |
Shown when neither the config nor the .dist has the key. |
apply |
now, reload or restart (the default); see below. |
A field without key or with an unknown type is left out without a message. A settings.json that is not valid
JSON adds an entry to the launcher's events, and the plugin gets no group.
label, hint, group and option labels are shown in the launcher's language, then English, then any language
present. A real example with every common type is settings.json of playerbots or lonelyice.citizens.
What saving does
- For every changed value, the launcher opens
modules/<name>.confbeside the server's config (configs/modules/<name>.conf), the file the server reads. If it does not exist yet, it is created as a copy of the plugin's.distfirst. (The setup wizard also copies the.distof every installed plugin there.) - The value is replaced in place, keeping the line's quotes and the file's comments and order. A key missing from
the file is appended at the end, quoted for
stringandchoice. - If the server is running, the launcher acts on the strongest
applyamong the changed fields:
apply |
After saving |
|---|---|
restart |
The server is restarted. |
reload |
The launcher sends reload config to the server console. |
now |
Nothing. |
When the server is not running, the values are simply read on its next start.
reload works only if your code reads the value again after a reload: call sConfigMgr->GetOption where the value
is used, or re-read your cached values in a WorldScript hook OnAfterConfigLoad(bool reload), as
lonelyice.citizens does. The core's config manager keeps what it read in memory and re-reads the files only on
reload config or a restart, so a now value saved through the launcher reaches sConfigMgr->GetOption only at
the next reload (another field's reload, or reload config typed in the console) or start. now suits only
values your code reads from the file by itself; for server options use reload or restart.
When the config is elsewhere
If the server's worldserver.conf is not in <server folder>/configs (a custom config path in lonelyice.ini),
nothing changes for a plugin: the launcher passes the config by its absolute path, the core reads the module configs
from the modules folder beside it, and Settings writes to that same folder. reload works there as well; no
module setting is passed as an AC_* variable.
Checklist
- Every
keyinsettings.jsonexists in the.dist, with a sensible default. minandmaxmatch what your code accepts; the code still validates, since the file can be edited by hand.applyisrestartunless your code really re-reads the value.- Texts have at least an
enentry.