Skip to content

Client Registration

Moth edited this page Aug 9, 2026 · 4 revisions

Client Registration

Butterfly API provides ClientRegistrar for common client-side registration tasks.

Client registration must only be performed on the physical client.

Getting the Client Registrar

From your ModContext:

MOD.client();

This should normally be used from your Fabric client initializer.

public class ExampleModClient implements ClientModInitializer {

    @Override
    public void onInitializeClient() {
        ClientRegistrar client = ExampleMod.MOD.client();
    }
}

Calling MOD.client() on a dedicated server will throw an IllegalStateException.

Block Render Layers

Cutout

MOD.cutout(EXAMPLE_BLOCK);

Multiple blocks can be supplied:

MOD.cutout(
        EXAMPLE_BLOCK,
        SECOND_BLOCK,
        THIRD_BLOCK
);

Cutout Mipped

MOD.cutoutMipped(EXAMPLE_BLOCK);

In the current 1.21.11 implementation, cutoutMipped(...) uses the same CUTOUT render layer as cutout(...).

Translucent

MOD.translucent(EXAMPLE_BLOCK);

Entity Renderers

MOD.entityRenderer(
        EXAMPLE_ENTITY,
        ExampleEntityRenderer::new
);

The equivalent ClientRegistrar method is:

MOD.client().entity(...);

Block Entity Renderers

MOD.blockEntityRenderer(
        EXAMPLE_BLOCK_ENTITY,
        ExampleBlockEntityRenderer::new
);

The equivalent ClientRegistrar method is:

MOD.client().blockEntity(...);

Screens

Register a handled screen with:

MOD.screen(
        EXAMPLE_SCREEN_HANDLER,
        ExampleScreen::new
);

Model Layers

MOD.modelLayer(
        EXAMPLE_MODEL_LAYER,
        ExampleModel::getTexturedModelData
);

Particle Factories

MOD.particleFactory(
        EXAMPLE_PARTICLE,
        ExampleParticle.Factory::new
);

Related Pages


Bootstrap Helpers

Butterfly API provides two small helpers for initialization code that should only run once:

  • Bootstrap
  • RunOnce

Bootstrap

Bootstrap groups one or more initialization steps and prevents them from being executed more than once.

Create one with:

private static final Bootstrap BOOTSTRAP =
        Bootstrap.create();

Then run your initialization:

public static void init() {
    BOOTSTRAP.run(
            ModItems::init,
            ModBlocks::init,
            ModSounds::init
    );
}

The first call runs every supplied step.

Later calls do nothing.

Checking Whether It Ran

BOOTSTRAP.hasRun();

Returns true after the bootstrap successfully runs.

Return Value

run(...) also returns a boolean:

boolean ran = BOOTSTRAP.run(
        ModItems::init,
        ModBlocks::init
);

It returns:

true

when the initialization runs for the first time.

It returns:

false

when the bootstrap has already run.

RunOnce

RunOnce is the smaller version of the same idea.

Create one with:

private static final RunOnce INIT =
        RunOnce.create();

Then:

public static void init() {
    INIT.run(() -> {
        // initialization
    });
}

Checking RunOnce

INIT.hasRun();

Like Bootstrap, run(...) returns true when the action runs and false when it has already run.

Bootstrap vs RunOnce

Use Bootstrap when initialization naturally consists of multiple steps:

BOOTSTRAP.run(
        ModItems::init,
        ModBlocks::init,
        ModEntities::init
);

Use RunOnce when you simply need to protect one action:

INIT.run(ModItems::register);

Both helpers are designed to prevent accidental duplicate initialization.

Clone this wiki locally