Blocks
Blocks are essential to the Minecraft world. They make up all the terrain, structures, and machines. Chances are if you are interested in making a mod, then you will want to add some blocks. This page will guide you through the creation of blocks, and some of the things you can do with them.
One Block to Rule Them All
Before we get started, it is important to understand that there is only ever one of each block in the game. A world consists of thousands of references to that one block in different locations. In other words, the same block is just displayed a lot of times.
Due to this, a block should only ever be instantiated once, and that is during registration. Once the block is registered, you can then use the registered reference as needed.
Unlike most other registries, blocks can use a specialized version of DeferredRegister, called DeferredRegister.Blocks. DeferredRegister.Blocks acts basically like a DeferredRegister<Block>, but with some minor differences:
- They are created via
DeferredRegister.createBlocks("yourmodid")instead of the regularDeferredRegister.create(...)method. #registerreturns aDeferredBlock<T extends Block>, which extendsDeferredHolder<Block, T>.Tis the type of the class of the block we are registering.- There are a few helper methods for registering block. See below for more details.
So now, let's register our blocks:
//BLOCKS is a DeferredRegister.Blocks
public static final DeferredBlock<Block> MY_BLOCK = BLOCKS.register("my_block", registryName -> new Block(...));
After registering the block, all references to the new my_block should use this constant. For example, if you want to check if the block at a given position is my_block, the code for that would look something like this:
level.getBlockState(position) // returns the blockstate placed in the given level (world) at the given position
.is(MyBlockRegistrationClass.MY_BLOCK);
This approach also has the convenient effect that block1 == block2 works and can be used instead of Java's equals method (using equals still works, of course, but is pointless since it compares by reference anyway).
Do not call new Block() outside registration! As soon as you do that, things can and will break:
- Blocks must be created while registries are unfrozen. NeoForge unfreezes registries for you and freezes them later, so registration is your time window to create blocks.
- If you try to create and/or register a block when registries are frozen again, the game will crash and report a
nullblock, which can be very confusing. - If you still manage to have a dangling block instance, the game will not recognize it while syncing and saving, and replace it with air.
Creating Blocks
As discussed before, we start by creating our DeferredRegister.Blocks:
public static final DeferredRegister.Blocks BLOCKS = DeferredRegister.createBlocks("yourmodid");