Skip to content

Configuration

Status: Implemented for typed options in one JSON file per scope, comments, saving, reloading and the generated Config page in the Mods screen. Enum, colour, list and keybind options, change callbacks per option, syncing server config to clients, custom config screens and TOML are Planned.

Function table: config. Guide: Config and a config screen.

Scopes and files

Scope File Typical use
CL_CONFIG_COMMON config/<mod id>.json Settings both sides read
CL_CONFIG_CLIENT config/<mod id>-client.json Visual preferences, HUD placement
CL_CONFIG_SERVER config/<mod id>-server.json Gameplay balance on a server

The files are flat JSON with dotted keys ("gift.rubies": 1). With the launcher, config/ is inside the instance’s folder.

Functions

cl_result cl_config_open(cl_config_scope scope, cl_config* out);
cl_result cl_config_define_bool(cl_config c, cl_str path, bool def);
cl_result cl_config_define_i32(cl_config c, cl_str path, int32_t def, int32_t min, int32_t max);
cl_result cl_config_define_f64(cl_config c, cl_str path, double def, double min, double max);
cl_result cl_config_define_str(cl_config c, cl_str path, cl_str def);
cl_result cl_config_comment(cl_config c, cl_str path, cl_str comment);   // the tooltip in the Config page
bool      cl_config_get_bool(cl_config c, cl_str path);
int32_t   cl_config_get_i32(cl_config c, cl_str path);
double    cl_config_get_f64(cl_config c, cl_str path);
cl_result cl_config_get_str(cl_config c, cl_str path, char* buf, size_t cap, size_t* out_len);
cl_result cl_config_set_bool / _i32 / _f64 / _str(cl_config c, cl_str path, value);
cl_result cl_config_save(cl_config c);
cl_result cl_config_reload(cl_config c);    // read the file again (keeps the definitions); fires config.reloaded when it changed

Defining a key that is missing from the file adds it with its default. A value outside its range or of the wrong type falls back to the default. All functions work in any context.

Reloads

  • A file the player edited is read again within about a second.
  • A hot reload of the mod re-reads its files.
  • Operators run /clight reload-config to reload every mod’s files.
  • The Config page in the Mods screen writes and reloads the file.

Each changed file fires config.reloaded (mod_id, file; filter = mod id). Lua: config:on_reload(function(event) ... end).

The Config page

Every mod that defines options gets a Config page in the Mods screen, generated from the definitions:

Type Control
bool toggle
integer or number with a range slider
anything else text box

The comment is the tooltip; labels come from the lang entries config.<mod id>.<path>, else the path.

Bindings

C C++ (clight::Config) Lua
cl_config_open(CL_CONFIG_COMMON, &c) clight::config::open(CL_CONFIG_COMMON) → Expected<Config> local config = cl.config.open("common")
cl_config_define_i32(c, "gift.rubies", 1, 0, 64) c.define_i32("gift.rubies", 1, 0, 64) config:define_i32("gift.rubies", 1, 0, 64)
cl_config_get_i32(c, "gift.rubies") c.get_i32("gift.rubies") config:get_i32("gift.rubies")
cl_config_comment(c, path, text) c.comment(path, text) config:comment(path, text)
cl_config_save(c) c.save() config:save()

In Lua, mod.config is a read-only table of the common file’s values as they were when the mod loaded; use cl.config.open for live values.

Example (Lua)

local config = cl.config.open("common")
config:define_i32("gift.rubies", 1, 0, 64)
config:comment("gift.rubies", "Rubies every player gets on join")
config:define_bool("gift.message", true)

cl.on("player.join", function(event)
  local n = config:get_i32("gift.rubies")
  if n > 0 then event.player:give("my_mod:ruby", n) end
  if config:get_bool("gift.message") then event.player:send_message("Here are your rubies!") end
end)

Planned

Enum, colour, list and keybind options; callbacks when one option changes; server config sent to clients that have the mod; a custom config screen (RML or code); categories in Celestial’s Client Settings screen (A client mod like the built-in client settings features); TOML files.