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.0to1.0.1. - Added something new? Raise the middle one and reset the last:
1.0.1to1.1.0. - Changed things so old worlds or other mods may break? Raise the first:
1.1.0to2.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.