Skip to content

Conventions

Status: Implemented. These are the rules clight.idl generates into clight.h, clight.hpp, the Lua binding and the WASM import table.

Every page in this folder documents one subsystem: what it is for, how to use it, and examples in C, C++ and Lua. The complete, always-current function lists are generated from the IDL into generated/: one table per module with the C, Lua and C++ name, the side, the context and the API version of every function. Anything not in those tables doesn’t exist yet; the hand-written pages mark such parts Planned.

Naming rules

Concept C C++ (clight.hpp) Lua
Module function cl_<module>_<verb> (cl_level_set_block) method on the handle: level.set_block(...); free function clight::level::set_block(level, ...) cl.<namespace>.<verb>(...), mirroring the C name (cl.level.set_block)
Function taking a handle first cl_living_set_health(e, 5) method: e.set_health(5) method: e:set_health(5)
Getter cl_living_health(e) e.health() the common ones are properties: e.health, e.name, e.pos; the call form is e:get_health()
Boolean query cl_entity_is_valid(e) e.is_valid() e:is_valid()
Handle type cl_entity clight::Entity userdata
Value struct cl_block_pos cl_block_pos (aggregate) cl.pos(x, y, z) (a table with a metatable)
Descriptor cl_block_desc + CL_BLOCK_DESC_INIT the same C struct (or a clight:: helper taking it) a table with the same keys
Enum value CL_DIRECTION_UP the C constant string "up"
Flags CL_BLOCK_REQUIRES_CORRECT_TOOL the C constant boolean key requires_correct_tool = true, or a table of names
Event CL_EV_BLOCK_BREAK, payload cl_ev_block_break clight::ev::BlockBreak "block.break"
Error cl_result < 0 clight::Expected<T> with a cl_result error a raised cl.Error (cl.try.<ns>.<fn>(...) returns false, err instead)

Functions whose C name carries its own family prefix inside a module keep it in Lua: cl_buf_write_i32 (module net) is cl.buf.write_i32, cl_task_cancel is cl.task.cancel, cl_player_give is cl.player.give. The older module spellings (cl.net.buf_write_i32, cl.entity.player_give) are the same functions and keep working.

Strings

  • C: cl_str { const char* ptr; size_t len; }. UTF-8, not required to be NUL-terminated. Use CL_STR("literal") or CL_STR_C(c_string).
  • Outgoing strings are written into a caller buffer: (char* buf, size_t cap, size_t* out_len). If cap is too small, the call returns CL_E_BUFFER_TOO_SMALL and sets *out_len to the size needed.
  • C++: std::string_view in, std::string out (the wrapper does the two-call pattern). clight::s(view) makes a cl_str, clight::sv(str) a view.
  • Lua: Lua strings.

Errors

Every fallible C function returns cl_result: CL_OK (0) on success, a negative CL_E_* code on failure (Error codes). Results go out through pointer parameters. Getters that can’t fail (other than on a stale handle) return the value directly and record the error in a thread-local cl_last_error(); they return a documented default (0, false or the null handle).

Descriptor structs and struct_size

typedef struct cl_block_desc {
    uint32_t struct_size;   // always first; set by CL_BLOCK_DESC_INIT
    cl_str   id;
    /* ... */
} cl_block_desc;

cl_block_desc d = CL_BLOCK_DESC_INIT;   // struct_size and every default

Always start from the _INIT macro. The engine reads only the fields that fit in struct_size, so a mod compiled against API 1.0 keeps working when a later minor version adds fields at the end.

Function entries

The generated tables list every function like this:

cl_result cl_level_set_block(cl_level level, cl_block_pos pos, cl_block_state state, cl_set_block_flags flags);
  • Context: where it may be called (ANY, MAIN, TICK, RENDER; Threading model).
  • Side: server, client or both.
  • Since: the API version that added it. On an older game, test with cl_core_has("level_set_block") / cl.has("level.set_block").
  • Owned: a returned handle you must release © or that the C++ class releases for you.

Callback signatures

C callbacks take a void* user as the last parameter: the pointer you passed when registering. The C++ wrapper uses it for its own lambda table (capturing lambdas work everywhere), so with the C++ helpers you capture instead.

Lua specifics

  • The global cl table holds all modules. mod is the current mod (mod.id, mod.version, mod.config, mod.persist, which survives hot reloads).
  • Positions accept cl.pos(x, y, z) or {x = ..., y = ..., z = ...}.
  • Block, block-state and item parameters accept id strings ("minecraft:stone").
  • Functions that would return cl_result raise a cl.Error (err.code, err.message) on failure. cl.try.<namespace>.<fn>(...) returns true, results... or false, err instead.