Home/Developer guide

Documentation / Developers

Build on ChiselTeam.

Add your blocks to Chisel's conversion system, query families at runtime, or use CTM as a standalone connected-texture library.

Java 25NeoForge 26.1.2.106GPL-3.0

Choose where to start

One existing family

Use a block tag. You don't need any Java code for this.

A new family

Register your addon's blocks with the experimental Chisel family API.

Runtime inspection

Use the stable read-only ChiselAPI lookup methods.

Connected textures only

Depend directly on CTM and use its JSON or datagen model system.

Query Chisel families

Use the stable, read-only API to find the family a block belongs to, or get all families available through a registry view.

Java
Optional<VariantFamily> family = ChiselAPI.getFamily(block, registryAccess);
Collection<VariantFamily> families = ChiselAPI.getFamilies(registryAccess);

Pass the active RegistryAccess. Family membership may include datapack-provided tag entries, so do not replace this lookup with a static map captured before data loading completes.

Register an addon family

Register your blocks through your own DeferredRegister.Blocks, then queue the family relationship during mod construction or common setup. Chisel resolves queued suppliers after registries are complete and freezes registration at load complete.

Java
public static final DeferredRegister.Blocks BLOCKS =
        DeferredRegister.createBlocks("examplemod");

public static final DeferredBlock<Block> MARBLE =
        BLOCKS.registerSimpleBlock("marble");
public static final DeferredBlock<Block> MARBLE_BRICKS =
        BLOCKS.registerSimpleBlock("marble_bricks");

ChiselAPI.registerFamily(
        Identifier.fromNamespaceAndPath("examplemod", "marble"),
        family -> family
                .variant(MARBLE)
                .variant(MARBLE_BRICKS, ChiselModelHandlers.CONNECTED)
);

You can set a logical name, choose a model handler, hide a selectable variant, or link a block tag with ChiselFamilyBuilder.

The registration API is experimental. Code under api.family.registration may change. The runtime lookup facade and core family/model types are the supported read-only surface.

Add CTM to a development environment

CTM is published through Modrinth's Maven endpoint. Limit the repository to Modrinth artifacts, then add CTM as a compile-only dependency if your runtime or mod distribution supplies it separately.

build.gradle
repositories {
    exclusiveContent {
        forRepository {
            maven {
                name = "Modrinth"
                url = "https://api.modrinth.com/maven"
            }
        }
        filter {
            includeGroup "maven.modrinth"
        }
    }
}

dependencies {
    compileOnly("maven.modrinth:ctmlib:${ctm_version}")
}

Continue with the CTM model reference for JSON definitions, model kinds, texture slots, and datagen.

What your addon handles

  • Your addon owns its blocks and registry entries.
  • Your addon owns its blockstates, models, textures, loot tables, recipes, and translations.
  • A Chisel model handler records runtime model metadata; it does not generate resources in your namespace.
  • Types annotated @ApiStatus.Internal are implementation details, even when Java visibility makes them accessible.
  • Chisel rejects duplicate family IDs, duplicate blocks or logical names, conflicting membership, null suppliers, empty families, and registrations made too late.

Contributing

We welcome bug fixes, translations, docs, and focused features. If you're planning a bigger change, open an issue to talk it through first. Send Chisel pull requests to the dev branch rather than master.

  • Keep changes focused; do not submit formatting-only pull requests.
  • Tell us what problem your change fixes and how you tested it.
  • For rendering fixes, include before-and-after images and the model JSON used to reproduce the issue.
  • Follow the existing Java style and avoid depending on internal APIs.