Skip to content

Versioning and dependencies

Status: Implemented for SemVer versions, depends, optional, breaks, load ordering and the API and game checks in the loader; the Celestial launcher installs dependencies from the website. provides, renaming ids with aliases, runtime service lookups and the multiplayer version handshake are Planned.

Version your mod with SemVer

version must be a SemVer 2.0 string: MAJOR.MINOR.PATCH, optionally with a pre-release (2.0.0-beta.3) and build metadata (+git.abc123, ignored for ordering). The website takes the version number from the manifest, and every upload of a project needs a new one.

Bump When Examples
PATCH Bug fixes. No new content, no changed save data, no changed payloads. Fixing a crash, a wrong drop, a typo in a lang file
MINOR Backwards-compatible additions New blocks or items, new optional config, new payloads that old peers can ignore
MAJOR Anything that breaks users, saves, other mods or older peers Removing content, renaming ids, changing a payload’s format, incompatible config changes

Never rename identifiers

Block and item ids are saved in worlds (mod blocks in the world’s position lists, mod items in custom_data). Renaming ruby_tools:ruby_block loses the placed blocks and turns the items into their plain base items. Renames with an alias are planned; until then, keep ids forever.

Declaring dependencies

"depends":  { "mana_core": "^2.1.0" },
"optional": { "recipe_viewer": ">=1.0" },
"breaks":   { "old_rubies": "*", "mana_core": "2.3.0" },
"load":     { "after": ["fancy_ores"], "before": [] }
Field Meaning Load order effect
depends Must be present with a matching version, or your mod doesn’t load (CLL-2001 missing, CLL-2002 wrong version) Dependencies load before you
optional If present, it must match the range; if absent, fine Loads before you when present
breaks Refuse to load together with these versions (CLL-2006) —
load.after / load.before Ordering hints without any requirement As stated
provides Planned: virtual ids you satisfy —

The range syntax (^, ~, comparators) is in clight.mod.json manifest schema (schema 1).

Choosing ranges

  • Depend on what you use. ^2.1.0 if you need something added in 2.1. Not *, which accepts a future 3.0 that may break you.
  • Don’t pin exact versions ("2.1.4") unless you must; it makes collections of mods hard to assemble.
  • Use breaks for known incompatibilities with a precise range, and explain it in your description.
  • For an optional feature, check at run time with cl_mod_is_loaded("recipe_viewer") (Lua cl.mod.is_loaded) instead of a hard dependency.

How the loader resolves a mod set

  1. Collect every manifest in mods/ (.clmod files are unpacked into mods/<id>/ first). Duplicate ids: CLL-1004.
  2. Check each mod’s api major (or the legacy clight range) and game range (CLL-2003, CLL-2004, CLL-2005). On a dedicated server, "side": "client" mods are skipped.
  3. Check depends and breaks. A mod that fails is disabled with the reason on the Mods screen.
  4. Sort topologically by depends, optional and load; ties are broken by mod id, so the order is identical on every machine. A cycle is CLL-2007.
  5. That order is the mod load order used for equal event priorities and for mod content ids.

The loader itself never downloads anything. The Celestial launcher installs a mod’s required dependencies into the instance when you install the mod from the website, and shows updates (Distribution).

Depending on the API and the game

Field Typical value Notes
api 1 The CLight API major you support. Probe newer minor-version features with cl.has() / cl_core_has().
game ">=26.3 <26.4" Only when your behaviour depends on a game version. Data mods often need it, because data formats change between game versions.

Data compatibility between your versions

Players update mods in existing worlds. For every release, think about what is saved:

Saved in How to evolve it
Mod blocks and items Keep the ids. Changing a block’s base block changes how existing positions look to vanilla clients.
Config files New options get their defaults; for a renamed option, read the old key once and write the new one
Your own files in /data (C/C++) Put a version number in the file

Test every release on a world saved with the previous one.

Pre-releases

2.0.0-beta.3 sorts before 2.0.0. On the website, upload pre-releases with the beta or alpha channel: they are only offered to players who opt in.