Skip to content

Registries

Status: Partly implemented. Blocks and items register in code and are vanilla-backed: a mod item is its vanilla_fallback item plus a component patch (custom_data {clight:"<id>"}, item_model, item_name, max_stack_size); a mod block is its vanilla base state in the chunk plus a server-side position list saved with the world. Lookups return virtual ids (0x40000000 | index) for mod content. Other registries in code (entity types, block entities, particles, menus, sound events, effects), registry iteration, tags, aliases and custom registries are Planned; data-pack registries work through the mod’s datapack/ folder.

Function table: registry. Concepts: Registries. The registry list: Registry list.

Functions

cl_result cl_block_register(const cl_block_desc* desc, cl_holder* out);   // MAIN, during lifecycle.register
cl_result cl_item_register(const cl_item_desc* desc, cl_holder* out);     // MAIN, during lifecycle.register
uint32_t  cl_holder_value(cl_holder h);                 // the raw id (0xFFFFFFFF before lifecycle.registries_frozen)
cl_result cl_block_lookup(cl_str id, cl_block_id* out); // vanilla and mod blocks
cl_result cl_item_lookup(cl_str id, cl_item_id* out);
cl_result cl_block_name(cl_block_id block, char* buf, size_t cap, size_t* out_len);
cl_result cl_item_name(cl_item_id item, char* buf, size_t cap, size_t* out_len);
cl_block_state cl_block_default_state(cl_block_id block);
cl_block_id    cl_block_state_block(cl_block_state state);
bool           cl_block_state_is(cl_block_state state, cl_str block);   // "minecraft:stone"
bool           cl_registries_frozen(void);

The descriptors (cl_block_desc, cl_item_desc) are documented on Blocks and block states and Items and item stacks. Registering outside lifecycle.register returns CL_E_WRONG_PHASE; an id that exists already returns CL_E_ALREADY_EXISTS (Lua returns the existing holder, so a hot reload doesn’t fail).

Bindings

C C++ Lua
cl_block_register(&d, &h) clight::registry::block_register(&d) → Expected<cl_holder>; clight::registry::block(d, behaviours) cl.blocks.register{ id = ..., ... } → holder
cl_item_register(&d, &h) clight::registry::item_register(&d); clight::registry::item(d, {.use = ...}) cl.items.register{ id = ..., ... }
cl_block_lookup(id, &b) clight::registry::block_lookup(id) → Expected<cl_block_id> cl.registry.block_lookup(id)
cl_block_name(b, ...) clight::registry::block_name(b) → Expected<std::string> cl.registry.block_name(b)
cl_block_state_is(s, id) cl_block_state_is(s, clight::s(id)) cl.registry.block_state_is(s, id), or event.block == id
cl_holder_value(h) clight::registry::holder_value(h) holder.raw (or cl.registry.holder_value(holder.raw))

In Lua, cl.registry("block") / cl.registry("item") is the same registry object as cl.blocks / cl.items. Ids without a namespace get your mod id ("ruby" → "my_mod:ruby"), and fields that name other content (vanilla_fallback, item, block, copy_from, copy_properties_from, creative_tab) accept a holder or an id string. Boolean keys named after a block flag (requires_correct_tool = true) set flags.

Example

cl.on("lifecycle.register", function()
  local block = cl.blocks.register{
    id = "ruby_block",
    copy_properties_from = "minecraft:emerald_block",
    vanilla_fallback = "minecraft:emerald_block",
    item = "ruby_block",
  }
  cl.items.register{ id = "ruby", vanilla_fallback = "minecraft:emerald" }
  cl.log("registered", block)   -- "my_mod:ruby_block"
end)

Planned

Typed registration for the other vanilla registries (entity types, block entity types, menus, particle types, sound events, effects, potions, attributes, recipe types and serializers, worldgen types), holder lookups for existing entries, iteration (size, entry_at), tag membership, renames (alias), dynamic-registry entries from code, and custom registries that other mods extend.