Skip to content

The manifest

Lesson 9.2

Every mod has a file called clight.mod.json in its top folder. It is the mod’s passport: the game reads it before it runs any code, and the Celestial website reads it when you upload the mod.

The template’s manifest

{
  "schema": 1,
  "id": "my_mod",
  "version": "1.0.0",
  "name": "My Mod",
  "description": "A CLight mod written in Lua.",
  "authors": [],
  "license": "MIT",
  "api": 1,
  "game": ">=26.3 <26.4",
  "side": "both",
  "sync": "optional",
  "runtime": { "type": "lua", "entry": "scripts/main.lua" },
  "permissions": []
}

It is JSON, not Lua: keys and strings use double quotes, and there is no comma after the last entry.

The fields

Field What it means
schema The manifest format. Always 1.
id The mod’s id. It must match the folder name under assets/ and datapack/, and it can’t change once the mod is published.
version The mod’s version, like 1.0.0. Raise it for every release.
name The name players see.
description One or two sentences about the mod.
authors A list of names: ["Alex", "Sam"].
license The licence: an SPDX id such as "MIT", "Apache-2.0", or "All-Rights-Reserved".
api The CLight API your mod is written for. Use 1.
game The game versions the mod works with.
side Where the mod runs: "client", "server" or "both".
sync Whether players need the mod to join a server that has it.
runtime "type": "lua" and the file that runs first.
permissions Extra things the mod asks the player for. Usually empty.

The fields up to runtime are required, except description, authors, api and game. Leave them in anyway: the website asks for a description, and api tells the game which API you expect.

Versions

Versions follow SemVer: three numbers, major.minor.patch.

  • Fixed a bug? Raise the last number: 1.0.0 to 1.0.1.
  • Added something new? Raise the middle one and reset the last: 1.0.1 to 1.1.0.
  • Changed things so old worlds or other mods may break? Raise the first: 1.1.0 to 2.0.0.

The website won’t accept the same version twice, so a new upload always needs a new number.

“api”: one mod, every build

"api": 1 means “this mod uses CLight API 1”. The API only ever grows: functions are added, never removed or changed. So a mod written for API 1 keeps working on every later Celestial build with API 1, without you rebuilding it.

New functions arrive in minor versions (1.1, 1.2, …). If you use one, check that it exists first, so your mod still loads on an older build:

if cl.has("gui") then
  -- draw something on the screen
end

print(cl.version)    --> 1.1.0
print(cl.api_major)  --> 1

cl.has knows modules ("gui", "sound"), single functions ("level.set_block") and features ("hot_reload.lua"). Unknown names give false.

side and sync

side decides where the mod is loaded:

side In the game you play On a dedicated server
"client" yes no
"server" yes (in singleplayer worlds) yes
"both" yes yes

Most mods use "both": a new item has to exist on the server (which owns the world) and on the client (which draws it). A mod that only adds a HUD or a keybind can be "client". Client and server explains the two sides.

sync says whether a player needs the mod to join a server that runs it: "required", "optional", "client_only" or "server_only". The website shows it on the mod’s page.

More fields

You won’t need these at first, but they exist:

Field Example Use
depends { "other_mod": ">=1.2" } Mods that must be installed. Without them your mod doesn’t load.
optional { "other_mod": ">=1.0" } Mods you work with if they are there.
breaks { "old_mod": "*" } Mods that can’t run next to yours.
icon "icon.png" The icon file, if it isn’t the default icon.png.
links { "homepage": "https://...", "issues": "https://..." } Shown on the mod’s page.
hot_reload true Reload scripts on save even outside development.
limits { "memory_mb": 64 } Raise the memory limit if your mod really needs it.

clight check tells you about mistakes in the manifest before the game or the website does:

> clight check
ok: my_mod 1.0.0

Try it

Your mod ruby_tools should be version 0.2.0, written by you, MIT licensed, needed on both sides, and players should need it to join. Write the manifest.

Show a solution
{
  "schema": 1,
  "id": "ruby_tools",
  "version": "0.2.0",
  "name": "Ruby Tools",
  "description": "Ruby gear and a ruby counter.",
  "authors": ["Alex"],
  "license": "MIT",
  "api": 1,
  "game": ">=26.3 <26.4",
  "side": "both",
  "sync": "required",
  "runtime": { "type": "lua", "entry": "scripts/main.lua" },
  "permissions": []
}

Run clight check to make sure it is valid.

Recap: clight.mod.json names your mod and says where it runs; raise version for every release and keep "api": 1.