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();
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.
.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
| Method | Purpose |
|---|---|
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.