Skip to content

Registering Blocks

In AnvilCraft addon development, registering blocks is similar to registering items, but involves more properties and model settings.

Open init.AddonBlocks.java, and you will see the following code:

java
public static final BlockEntry<Block> EXAMPLE_BLOCK = REGISTRUM
    .block("example_block", Block::new)
    .simpleItem()
    .register();

This statement is an example of registering a block, where example_block is the ID of the block you are about to register, and Block::new is a reference to your block class constructor.

This chapter will detail how to use REGISTRUM.block()

After using the REGISTRUM.block() method, you will get a BlockBuilder object that has a .register() method. Calling it returns a BlockEntry, and the corresponding block will be automatically registered at the appropriate time.

BlockBuilder.initialProperties()

This method is used to set the initial properties of a block, based on a complete copy of an existing block:

java
public static final BlockEntry<Block> EXAMPLE_BLOCK = REGISTRUM
    .block("example_block", Block::new)
    .initialProperties(() -> Blocks.IRON_BLOCK)
    .simpleItem()
    .register();

This example shows how to set initial properties for a registered block, inheriting from iron block properties.

BlockBuilder.properties()

This method is used to modify specific properties of a block. It can be called multiple times to accumulate modifications:

java
public static final BlockEntry<Block> EXAMPLE_BLOCK = REGISTRUM
    .block("example_block", Block::new)
    .initialProperties(() -> Blocks.STONE)
    .properties(p -> p.lightLevel(state -> 5).noOcclusion())
    .simpleItem()
    .register();

This example shows how to set the light level and no-occlusion properties for a block.

BlockBuilder.tag()

This method is used to set tags for a block. It can be called multiple times to add multiple tags:

java
public static final BlockEntry<Block> EXAMPLE_BLOCK = REGISTRUM
    .block("example_block", Block::new)
    .initialProperties(() -> Blocks.STONE)
    .tag(BlockTags.MINEABLE_WITH_PICKAXE, BlockTags.NEEDS_STONE_TOOL)
    .simpleItem()
    .register();

This example shows how to add a block to the "mineable with pickaxe" and "needs stone tool" tags.

BlockBuilder.blockstate()

This method is used to set the blockstate and model for a block. By default, a simple cube_all model is automatically generated:

java
public static final BlockEntry<Block> EXAMPLE_BLOCK = REGISTRUM
    .block("example_block", Block::new)
    .initialProperties(() -> Blocks.STONE)
    .blockstate((ctx, provider) -> provider.simpleBlock(ctx.getEntry()))
    .simpleItem()
    .register();

This example shows how to set a simple block model for a block.

BlockBuilder.item()

This method is used to register a corresponding item for a block, returning an ItemBuilder for further configuration of item properties:

java
public static final BlockEntry<Block> EXAMPLE_BLOCK = REGISTRUM
    .block("example_block", Block::new)
    .initialProperties(() -> Blocks.STONE)
    .blockstate((ctx, provider) -> provider.simpleBlock(ctx.getEntry()))
    .item()
    .properties(p -> p.rarity(Rarity.UNCOMMON))
    .build()
    .register();

This example shows how to register an item for a block and set item properties.

BlockBuilder.simpleItem()

This is a convenience method for quickly registering a basic item for a block (equivalent to item().build()):

java
public static final BlockEntry<Block> EXAMPLE_BLOCK = REGISTRUM
    .block("example_block", Block::new)
    .initialProperties(() -> Blocks.STONE)
    .blockstate((ctx, provider) -> provider.simpleBlock(ctx.getEntry()))
    .simpleItem()
    .register();

This example shows how to use simpleItem() to quickly register an item for a block.

BlockBuilder.recipe()

This method is used to set the recipe for a block:

java
public static final BlockEntry<Block> EXAMPLE_BLOCK = REGISTRUM
    .block("example_block", Block::new)
    .initialProperties(() -> Blocks.STONE)
    .blockstate((ctx, provider) -> provider.simpleBlock(ctx.getEntry()))
    .simpleItem()
    .recipe((ctx, provider) -> ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, ctx.get(), 4)
        .pattern("XX")
        .pattern("XX")
        .define('X', Items.STONE)
        .unlockedBy("has_stone", RegistrumRecipeProvider.has(Items.STONE))
        .save(provider))
    .register();

This example shows how to add a shaped crafting recipe for a block.

Custom Block Classes

In addition to using the vanilla Block class, you can also create custom block classes:

java
public class CustomBlock extends Block {
    public CustomBlock(Properties properties) {
        super(properties);
    }

    @Override
    public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean isMoving) {
        // Add custom logic
        super.onPlace(state, level, pos, oldState, isMoving);
    }
}

Then use it when registering:

java
public static final BlockEntry<CustomBlock> CUSTOM_BLOCK = REGISTRUM
    .block("custom_block", CustomBlock::new)
    .initialProperties(() -> Blocks.STONE)
    .simpleItem()
    .register();

Block Registration Best Practices

  1. Naming Conventions

    • Use lowercase letters and underscores for block IDs
    • Keep naming consistent and descriptive
  2. Property Settings

    • Always set appropriate initial properties
    • Add appropriate tags based on block functionality
  3. Models and Rendering

    • Provide appropriate models for blocks
    • Consider block lighting and occlusion properties
  4. Recipe Design

    • Provide reasonable crafting recipes for blocks
    • Ensure recipes are balanced and don't break game experience
  5. Timely Registration

    • Ensure you call the register() method in the mod main class constructor
    • Example: AddonBlocks.register();

Complete Example

Here is a complete custom block registration example:

java
public static final BlockEntry<Block> RUBY_BLOCK = REGISTRUM
    .block("ruby_block", Block::new)
    .initialProperties(() -> Blocks.IRON_BLOCK)
    .properties(p -> p.lightLevel(state -> 3))
    .tag(BlockTags.MINEABLE_WITH_PICKAXE, BlockTags.BEACON_BASE_BLOCKS)
    .blockstate((ctx, provider) -> provider.simpleBlock(ctx.getEntry()))
    .simpleItem()
    .recipe((ctx, provider) -> ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, ctx.get())
        .pattern("XXX")
        .pattern("XXX")
        .pattern("XXX")
        .define('X', ModItems.RUBY)
        .unlockedBy("has_ruby", RegistrumRecipeProvider.has(ModItems.RUBY))
        .save(provider))
    .register();

This example demonstrates how to:

  • Create a block based on iron block properties
  • Set the block's light level
  • Add appropriate tags
  • Set a simple block model
  • Register an item for the block
  • Add a crafting recipe

Released under the CC-BY-NC-SA 4.0 License.