Skip to main content

Register Blocks

Simple Block

public static final BlockEntry<Block> DECORATIVE_STONE = REGISTRYLIB
.block("decorative_stone", Block::new)
.initialProperties(() -> Blocks.STONE)
.lang("Decorative Stone")
.simpleItem()
.register();

Full Block with Custom Loot and Tags

public static final BlockEntry<Block> MAGIC_ORE = REGISTRYLIB
.block("magic_ore", Block::new)
.initialProperties(() -> Blocks.IRON_ORE)
.properties(p -> p.strength(4.0F, 5.0F).requiresCorrectToolForDrops())
.lang("Magic Ore")
.loot((tables, b) -> tables.add(b, tables.createOreDrop(b, SimpleItemExample.COPPER_COIN.get())))
.addTag(BlockTags.MINEABLE_WITH_PICKAXE, BlockTags.NEEDS_IRON_TOOL)
.item(item -> item.addTooltip((collector, stack) -> {
collector.node(new SubNode.Basic(Component.literal("§5Drops coins when mined")), true, false);
}))
.register();
warning

Registering a Block does NOT automatically create a BlockItem. You must explicitly call .simpleItem() or .item(...) to generate one.

Tinted Block Models

Use tintedCube(...) when the block model needs face-level tintindex values, then use constantTint(...) or tintSource(...) for the generated BlockItem model:

import com.gto.registrylib.util.color.RgbColor;

public static final BlockEntry<Block> TIN_BLOCK = REGISTRYLIB
.block("tin_block")
.constantTint("block/templates/storage_cube", RgbColor.of(0xC8D8E8))
.simpleItem()
.register();

constantTint(texturePath, color) writes a simple cube block model with tintindex: 0 on each face, registers a block tint source, and creates a tinted BlockItem model pointing at the block model. RgbColor accepts only 0xRRGGBB; RegistryLib converts it to opaque ARGB for both block and item tint paths. The template PNG must already exist under assets/<modid>/textures/..., or be generated once by a general resource provider. Use tintedCube(texturePath, tintIndex) when you need to control the face tint index separately.

For batch registration, move the visual rule into a preset:

TextureRef storageTemplate = REGISTRYLIB.textureRef("block/templates/storage_cube");

REGISTRYLIB.block("lead_block")
.visual(BlockVisualPreset.constantTintedCube(storageTemplate, RgbColor.of(0x6E7380)))
.simpleItem()
.register();

For layered block models, combine a particle texture with one or more BlockModelLayer entries:

TextureRef base = REGISTRYLIB.textureRef("block/templates/storage_cube");
TextureRef overlay = REGISTRYLIB.textureRef("block/templates/storage_overlay");

REGISTRYLIB.block("layered_storage_block")
.visual(BlockVisualPreset.layeredCube(
base,
RgbColor.of(0x6E7380),
BlockModelLayer.untinted(base),
BlockModelLayer.tinted(overlay, 0, true)))
.debugTint()
.simpleItem()
.register();

debugTint() logs the highest model tintindex, registered block tint source count, known colors, BlockItem tint source count, and warns when a model references a tint index without enough block tint sources. If you call raw Minecraft BlockTintSources.constant(int) yourself, pass ARGB; 0xRRGGBB has alpha 0 there. Prefer RegistryLibTintSources.blockConstant(RgbColor) or BlockBuilder.blockConstantTint(RgbColor) when you want opaque RGB behavior.

important

.texture(path, imageSupplier) generates a block texture PNG. Use modelTexture(...), existingTexture(...), tintedCube(texturePath, tintIndex), or constantTint(texturePath, color) when the model should reference an existing shared texture.

Use TextureRef.mc("block/iron_block") or TextureRef.of(id) for vanilla or third-party cube textures; string overloads resolve inside the current mod namespace.

Hand-Written Blockstate

Use .noBlockstate() when you provide the blockstate JSON yourself and do not want datagen to generate one:

public static final BlockEntry<Block> SPECIAL_BLOCK = REGISTRYLIB
.block("special_block", Block::new)
.noBlockstate()
.lang("Special Block")
.simpleItem()
.register();

The block is excluded from NeoForge's blockstate validation so datagen no longer throws. The BlockItem will receive a flat item model by default; override via .item(b -> b.model(...)) to reference a hand-written block model. You must supply assets/<modid>/blockstates/special_block.json yourself.

Common API Lookup

MethodPurpose
block(name, factory)Create a BlockBuilder
initialProperties(supplier)Set the source of initial block properties
properties(...)Refine properties after initial copy
simpleItem()Create the default BlockItem
item(...)Customize the BlockItem
defaultLoot()Generate basic self-drop loot table
loot(...)Supply a custom loot table callback
noBlockstate()Skip blockstate datagen for hand-written JSON
tintedCube(tintIndex)Generate a cube block model with face tint indices using the block's own texture path
tintedCube(texturePath, tintIndex)Generate a tinted cube block model referencing a shared texture
constantTint(RgbColor)Register opaque block tint and generate a tinted BlockItem model using the block's own model
constantTint(texturePath, RgbColor)Generate a tinted cube block model, register block tint, and generate a tinted BlockItem model from a shared texture
constantTint(texture, RgbColor)TextureRef variant for shared textures
tintSource(sources...)Generate a BlockItem model with custom item tint sources
blockTintSource(sources...)Register runtime block/world tint sources
blockConstantTint(RgbColor) / blockConstantTint(ArgbColor)Register block tint colors explicitly
layeredCube(particle, layers...)Generate a full-cube layered block model with per-layer tint and translucency settings
debugTint()Log and validate model tint indices against configured tint sources
modelTexture(texturePath) / existingTexture(texturePath)Reference an existing texture without writing a PNG
visual(BlockVisualPreset.constantTintedCube(...))Reuse a shared block visual rule in batch registration
addTag(...)Add one or more block tags
register()Complete registration and return BlockEntry<T>

Common Patterns

Simple BlockItem: Use .simpleItem() when the default BlockItem is enough. Switch to .item(...) only for custom Item types or properties.

Shared properties via Group: When multiple blocks share the same defaults (e.g., machine casings), centralize with the Group System through blockProperties(...) or itemProperties(...).

BlockEntity later: Keep block registration independent first, then attach BlockEntity behavior separately. See Register Block Entities.

See Also