Forge Java · Block interaction

Right click,Let the squares shine.

Add a complete new block to the existing Forge 1.20.1-47.4.20 project. It will remember the on and off state, switch appearance and emit 15 levels of light when right-clicked.

Minecraft 1.20.1 Forge 47.4.20 Java 17 About 45-60 minutes
Current: OffClick on the square, simulating right-clicking in the game

Mission · Let’s look at the final results first

What is completed is not just a piece of code, but a complete block development chain.

After learning, you can explain what Java, block state, and resource JSON are responsible for, and be able to verify the results yourself in the game.

01 · REGISTER

Registering blocks and items

Get unique ID examplemod:right_click_light_blockAnd make it appear in the pattern creation column.

02 · STATE

Save the on-off state

Use Boolean attributes LIT Save "on" or "off", and default to false.

03 · EVENT

Process player right click

Rewrite use Method: The server switches state and plays the lever click sound at the same time.

04 · RESOURCES

Connect Appearance to Data

Added block state, two models, name, drop table and workbench crafting recipe.

Completion criteria:Execute /give @s examplemod:right_click_light_block The block can be obtained; it will not emit light after being put down; the first right click will light up and illuminate the surroundings; the second right click will extinguish it; it will drop itself after being destroyed.

File map · Files should be placed in the right location

The path is a part of the resource ID, and all characters are disconnected.

This time a Java class and seven resource files are added, while the access category and two language files are modified. All resource filenames are lowercased in English and underlined.

Key file structure of this lesson
src/main/
├─ java/com/example/examplemod/
│  ├─ ExampleMod.java
│  └─ block/RightClickLightBlock.java
└─ resources/
   ├─ assets/examplemod/
   │  ├─ blockstates/right_click_light_block.json
   │  ├─ models/block/right_click_light_block_off.json
   │  ├─ models/block/right_click_light_block_on.json
   │  ├─ models/item/right_click_light_block.json
   │  └─ lang/zh_cn.json + en_us.json
   └─ data/examplemod/
      ├─ loot_tables/blocks/right_click_light_block.json
      └─ recipes/right_click_light_block.json

block Package

Java behavior: how to respond to the player's right click and how to change the state.

ExampleMod

Registration entrance: Tell Forge that this block and corresponding items exist.

assets

The client displays: light and off models, item models and Chinese and English names.

data

Game rules: how to drop blocks and how to synthesize them in the workbench.

Concept · Understand first before coding

One block, two states:lit=false with lit=true.

Core algorithm: negate the current Boolean value
boolean willBeLit = !state.getValue(LIT);
Why not use normal Java fields?one Block Objects are used by many world locations.BlockState Each position can be saved independently, so the light on the left can be on and the light on the right can be off.

How to divide the work between the client and the server?

Client Client

Display hand movements, block models and lighting. Refresh the screen after receiving the new status of server synchronization.

Server Server

Really modify the state of the world. For code !level.isClientSide() Ensure that the same right-click is only modified once.

Step 1·Write block class

Create RightClickLightBlock.java, let the squares learn to respond to the right key.

In src/main/java/com/example/examplemod/block . Below is the full code that has been compiled in the current project.

RightClickLightBlock.java
package com.example.examplemod.block;

import net.minecraft.core.BlockPos;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.phys.BlockHitResult;

public class RightClickLightBlock extends Block {
    public static final BooleanProperty LIT = BlockStateProperties.LIT;

    public RightClickLightBlock(Properties properties) {
        super(properties);
        registerDefaultState(stateDefinition.any().setValue(LIT, false));
    }

    @Override
    protected void createBlockStateDefinition(
            StateDefinition.Builder<Block, BlockState> builder) {
        builder.add(LIT);
    }

    @Override
    public InteractionResult use(BlockState state, Level level,
            BlockPos pos, Player player, InteractionHand hand,
            BlockHitResult hit) {
        boolean willBeLit = !state.getValue(LIT);

        if (!level.isClientSide()) {
            level.setBlock(pos, state.setValue(LIT, willBeLit), Block.UPDATE_ALL);
            level.playSound(null, pos, SoundEvents.LEVER_CLICK,
                    SoundSource.BLOCKS, 0.35F, willBeLit ? 0.7F : 0.5F);
        }

        return InteractionResult.sidedSuccess(level.isClientSide());
    }
}
1

Statement LIT

BooleanProperty There are only two values, true and false, which just represent the light switch.

2

Set default status

The newly placed block defaults to lit=falseSo it doesn't glow at first.

3

Add attributes to state definition

It's missing. builder.add(LIT) Property errors occur when starting or placing blocks.

4

Only change the world on the server side

Block.UPDATE_ALL Neighbors will be updated and the new status will be synchronized to the client.

Step 2 · Register blocks and items

In ExampleMod.java Access the existing registration system.

To be able to hold a block in your hand, you usually need to register it at the same time Block with BlockItem.

Import new class
import com.example.examplemod.block.RightClickLightBlock;
Registration Block and BlockItem
public static final RegistryObject<Block> RIGHT_CLICK_LIGHT_BLOCK =
        BLOCKS.register("right_click_light_block",
                () -> new RightClickLightBlock(BlockBehaviour.Properties.of()
                        .mapColor(MapColor.COLOR_CYAN)
                        .strength(1.5F)
                        .lightLevel(state ->
                                state.getValue(RightClickLightBlock.LIT) ? 15 : 0)));

public static final RegistryObject<Item> RIGHT_CLICK_LIGHT_BLOCK_ITEM =
        ITEMS.register("right_click_light_block",
                () -> new BlockItem(
                        RIGHT_CLICK_LIGHT_BLOCK.get(), new Item.Properties()));

Added to creative mode inventory

Project label and building block tags
// EXAMPLE_TAB 的 displayItems 中
output.accept(RIGHT_CLICK_LIGHT_BLOCK_ITEM.get());

// addCreative 方法中
if (event.getTabKey() == CreativeModeTabs.BUILDING_BLOCKS) {
    event.accept(RIGHT_CLICK_LIGHT_BLOCK_ITEM);
}
Common missing items:When only Block is registered and BlockItem is not registered, the block may exist in the registry but cannot appear normally in the backpack.

Step 3 · Connection status, appearance and data

Let's have two. LIT The state selects two different models.

This lesson reuses the original Minecraft redstone lamp texture, so there is no need to add a new PNG. The block state file is responsible for selecting the model, and the model file is responsible for selecting the texture.

blockstates/right_click_light_block.json
{
  "variants": {
    "lit=false": {
      "model": "examplemod:block/right_click_light_block_off"
    },
    "lit=true": {
      "model": "examplemod:block/right_click_light_block_on"
    }
  }
}
models/block/..._off.json
{
  "parent": "minecraft:block/cube_all",
  "textures": {
    "all": "minecraft:block/redstone_lamp"
  }
}
models/block/..._on.json
{
  "parent": "minecraft:block/cube_all",
  "textures": {
    "all": "minecraft:block/redstone_lamp_on"
  }
}
models/item/right_click_light_block.json
{
  "parent": "examplemod:block/right_click_light_block_off"
}

Add Chinese and English names

zh_cn.json
"block.examplemod.right_click_light_block":
  "右键发光方块"
en_us.json
"block.examplemod.right_click_light_block":
  "Right-click Light Block"

Drop itself after destruction

loot_tables/blocks/right_click_light_block.json
{
  "type": "minecraft:block",
  "pools": [{
    "rolls": 1,
    "entries": [{
      "type": "minecraft:item",
      "name": "examplemod:right_click_light_block"
    }],
    "conditions": [{
      "condition": "minecraft:survives_explosion"
    }]
  }]
}

Add workbench recipe

recipes/right_click_light_block.json
{
  "type": "minecraft:crafting_shaped",
  "pattern": ["GGG", "GRG", "GGG"],
  "key": {
    "G": { "item": "minecraft:glowstone_dust" },
    "R": { "item": "minecraft:redstone_lamp" }
  },
  "result": {
    "item": "examplemod:right_click_light_block"
  }
}

Step 4 · Compile, run, and accept

Let Gradle check the code first, and then enter the game to do a complete test.

1

Fast compilation

PowerShell
.\gradlew.bat compileJava processResources
2

Start development client

PowerShell
.\gradlew.bat runClient
3

Get the squares and cut them to the night.

Minecraft Chat Bar
/give @s examplemod:right_click_light_block
/time set midnight
CHECK 1

Extinguishes when put down

The appearance is that the redstone lamp is unlit and there is no additional lighting around it.

CHECK 2

Light up after right-clicking

The appearance brightens, 15 levels of light appear around it, and a click sound is heard.

CHECK 3

Right click again to turn off

Description LIT can move from false to true, and then return to false.

CHECK 4

Re-entering the world.

The block still maintains the state before leaving, indicating that BlockState is saved.

CHECK 5

Dropped after destruction

Blocks will drop the same re-placeable block item.

CHECK 6

Formula Available

Eight fluorite powder surrounding a redstone lamp can be used to synthesize new blocks.

The current project has been verified:compileJava,processResources With complete build All displayed BUILD SUCCESSFUL.

Debug · Look at the phenomenon to find the cause

Don't rely on guessing, first determine whether the error belongs to Java, registration or resource layer.

PhenomenonMost likely causeInspection method
The attribute does not exist when startingForget builder.add(LIT)Confirm that attributes are both declared and state definitions are added.
/give Prompt unknown itemsThe registered name is different, or the BlockItem is not registeredFull text search right_click_light_blockAnd that's exactly the same thing.
Display purple and black gridModel path or JSON syntax errorIn latest.log Search Unable to load model.
The right button changes but does not emit light.lightLevel Same LIT not readConfirm expression returns 15 or 0.
No response when right-clickingThe item in hand preempts the interaction, or only changes the status on the clientTest empty-handed first; confirm server call setBlock.
No falling after destructionThe drop table is missing or the directory is wrongConfirm that the path is data/examplemod/loot_tables/blocks.
Recommended order:First check whether Gradle is compiled successfully, and then latest.log, the resource path is checked again and then the code is changed repeatedly. For one reason at a time, re-test it.

Practice · From doing it to changing it yourself

Only one variable is changed at a time, the result is predicted first, and then the verification is run.

LEVEL 1

Lower Brightness

Change the lighting brightness from 15 to 8 and compare the lighting range at night.

LEVEL 2

Change sound

Try SoundEvents.AMETHYST_BLOCK_CHIME.

LEVEL 2

Only empty hands allowed

Check player.getItemInHand(hand).isEmpty().

LEVEL 3

Add particles

Research animateTick with ParticleTypes.END_ROD.

Five-minute self-test

1. Why do I need to register BlockItem after registering Block?

Block is a block in the world, and BlockItem is an item that can be taken and placed in the backpack. Without BlockItem, it would be difficult for students to obtain and place the block through the normal item system.

2. What is the difference between BlockState and ordinary Java fields?

BlockState belongs to the specific block position in the world, and each light can save its own value; ordinary fields belong to the shared Block object.

3. Why is setBlock only called on the server side?

The server owns the final state of the world and is responsible for synchronizing the results to the client. Modifying both sides will cause repeated execution or status out of synchronization.

4. What are blockstates and model JSON responsible for respectively?

blockstates selects a model based on attribute values; the model file then determines the geometry and texture resources.

5. Where should you check first when you see purple and black grids?

First check the model file name, path, namespace and JSON syntax. The command has been able to obtain the block, which usually means that Java registration has been successful.

Lesson complete

You have completed a truly interactive Forge block.

Remember this development chain: register ID {LIT status ⁇ use() → lighting 15/0 → on/off model → game acceptance. In the future, you can continue to expand from this method to make doors, buttons, machine switches and multi-state decorative blocks.