Skip to content

Block Set API

MehVahdJukaar edited this page Jul 25, 2026 · 1 revision

Block Set API

Finds every wood type, leaves type or whatever else you define that's installed, from any mod, and lets you register a block for each one.

Say you want a shelf made of every wood in the game. You can't know at compile time which mods the player has. This detects them at runtime and calls you back once per type, so you register mymod:oak_shelf, biomesoplenty:maple_shelf and so on, for whatever is actually there. Then Runtime Resource Packs generates the models and textures for them.

Detection is automatic: it looks at every registered block and guesses sibling ids (maple_log next to maple_planks), which gets most mods right without special casing.

Getting Started

WoodType and LeavesType come built in. To register a block per wood type:

public static void init() {
    BlockSetAPI.addDynamicBlockRegistration(MyMod::registerShelves, WoodType.class);
}

private static void registerShelves(Registrator<Block> event, Collection<WoodType> woodTypes) {
    for (WoodType wood : woodTypes) {
        ResourceLocation id = MyMod.res(wood.getVariantId("shelf"));   // mymod:oak_shelf
        Block block = new ShelfBlock(wood.copyProperties());
        event.register(id, block);

        // register it back onto the type, with a unique key
        wood.addChild("mymod:shelf", block);
    }
}

Important

Always addChild your block back onto the type. That's what makes type swapping and the resource generation helpers find it later. One child per block or item is enough, not both.

A BlockType is an id plus a bag of children. getVariantId, getBlockOfThis(key), mainChild(), getReadableName(). WoodType adds planks, log, canBurn(), getColor(), copyProperties() and conversions to vanilla's own WoodType/Boat.Type.

Once things are registered you can move between types:

Block spruceShelf = BlockSetAPI.changeBlockType(oakShelf, oakType, spruceType);

That's also how "this recipe, but in every wood" works, see ResourceSink.addBlockTypeSwapRecipe.

Example: BlockSetRegistryExample

Defining your own set

Subclass BlockType and BlockTypeRegistry. The registry looks at a block and says whether it defines a new type; the type declares its children:

public static class FlowerTypeRegistry extends BlockTypeRegistry<FlowerType> {
    protected FlowerTypeRegistry() {
        super(FlowerType.class, "flower_type");
    }

    @Override
    public Optional<FlowerType> detectTypeFromBlock(Block block, ResourceLocation blockId) {
        if (block instanceof FlowerBlock f) return Optional.of(new FlowerType(f));
        return Optional.empty();
    }

    @Override
    public FlowerType getDefaultType() {
        return POPPY;
    }

    public static final FlowerType POPPY = new FlowerType((FlowerBlock) Blocks.POPPY);
}
@Override
protected void initializeChildrenBlocks() {
    // guesses ids like "double_poppy" next to "poppy"
    var doubleFlower = findRelatedEntry("double", BuiltInRegistries.BLOCK);
    if (doubleFlower != null) this.addChild("double_flower", doubleFlower);
    this.addChild("flower", shortFlower);
}

Register the definition on init with BlockSetAPI.registerBlockSetDefinition(new FlowerTypeRegistry()).

Fixing detection

For mods detection gets wrong, add a finder by hand. It only applies if that mod is installed, so it's safe to add unconditionally:

WoodTypeRegistry.INSTANCE.addSimpleFinder("some_mod_id", "yellow_wood")
        .log("yellow_wood_log")
        .planks("yellowish_plank")
        .childBlock("stick", "stick_light_yellow")
        .build();

BlockSetAPI.addBlockTypeRemover(type, id) drops a wrongly detected one.

extra_debug in the common config dumps every detected type to .minecraft/debug/, and extra_children_debug also lists their children.

Block colors

BlocksColorAPI is the same idea for the 16 dye colors. It groups colored block families automatically, modded ones included:

DyeColor color = BlocksColorAPI.getColor(stack.getItem());
Block newBlock = BlocksColorAPI.changeColor(oldState.getBlock(), color);

Item redTerracotta = BlocksColorAPI.getColoredItem("terracotta", DyeColor.RED);

Example: BlockColorExample

Clone this wiki locally