Now that we have items working, it's time to create a custom block. Blocks in Minecraft are closely tied to their items (the BlockItem is what you hold in your inventory), so our registry helper will handle registering both at once.
ItemRegistry here to register the BlockItem automatically.Creating the Block Registry
Create a new BlockRegistry class in your registry package. We will add a private helper method called registerBlock that simultaneously registers the block and its corresponding BlockItem:
The registerBlock helper registers the block under your mod's namespace, then immediately registers a matching BlockItem so the block is obtainable as an item. Both share the same registry name, which is the standard Minecraft convention.
Defining a Block
Add a public static final field for your first block. We will create a simple dirt variant called New Dirt by copying all properties from vanilla dirt:
ofFullCopy copies every property from the target block, including hardness, blast resistance, sound and tool requirement. You can also use the builder pattern (BlockBehaviour.Properties.of()...) to set properties manually.
Call BlockRegistry.init() from CommonClass.init():
Block Model and Texture
Create the block model JSON at src/main/resources/assets/examplemod/models/block/new_dirt.json:
The cube_all parent applies the same texture to every face. Create a 16×16 PNG texture at src/main/resources/assets/examplemod/textures/block/new_dirt.png.
Blocks also need an item model (for the inventory icon). Create src/main/resources/assets/examplemod/models/item/new_dirt.json that simply inherits the block model:
Blockstate File
The blockstate file maps block property combinations to model variants. For a simple block with no properties, there is just one variant with an empty string key. Create src/main/resources/assets/examplemod/blockstates/new_dirt.json:
Creative Tab for Blocks
Open CreativeTabRegistry and add a second tab for your blocks, or add the block to the existing items tab. Here we'll keep them separate:
Language File
Add display names for the block and the new creative tab to your en_us.json language file:
Testing In-Game
Run the Fabric Client or NeoForge Client. Open creative mode and you should see your new Blocks tab with New Dirt in it. Place the block and verify it renders correctly with your texture. You can also use:
Breaking the block will not drop anything yet, as that requires a loot table, which we cover in the Data Generation tutorials coming up next.
You can find the source for this tutorial here:
View Source on GitHubData Generation: Block & Item Models (MultiLoader 1.21+)
Configure NeoForge datagen to write resources into the common project, create BlockStateProvider and ItemModelProvider classes, and hook them into GatherDataEvent to auto-generate model and blockstate files.
Continue →