Creating a Custom Block
Blocks follow the same DeferredRegister pattern as items, with a bit more configuration for how they behave in the world.
package com.example.examplemod;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.material.MapColor;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
public class ModBlocks {
public static final DeferredRegister<Block> BLOCKS =
DeferredRegister.create(ForgeRegistries.BLOCKS, "examplemod");
public static final RegistryObject<Block> RUBY_ORE =
BLOCKS.register("ruby_ore", () ->
new Block(Block.Properties.of()
.mapColor(MapColor.STONE)
.strength(3.0f, 3.0f)
.requiresCorrectToolForDrops()));
}
strength(hardness, resistance) controls mining time and explosion resistance, and requiresCorrectToolForDrops() means the block only drops an item if broken with a tool that meets its harvest level (a pickaxe, in this case), just like vanilla ore.
Registering the matching BlockItem
A registered block has no inventory representation on its own, you need a companion BlockItem so it can actually be picked up and placed:
public static final RegistryObject<Item> RUBY_ORE_ITEM =
ModItems.ITEMS.register("ruby_ore", () ->
new BlockItem(ModBlocks.RUBY_ORE.get(), new Item.Properties()));
Blockstates and models
Like items, blocks need JSON resources to actually render:
assets/examplemod/blockstates/ruby_ore.json, maps the block's state(s) to a model.assets/examplemod/models/block/ruby_ore.json, describes its geometry and textures (a simple cube uses the built-inblock/cube_allparent).assets/examplemod/models/item/ruby_ore.json, usually just points back at the block model, so it looks the same in the inventory as it does placed.