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.
Registering blocks and items
Get unique ID examplemod:right_click_light_blockAnd make it appear in the pattern creation column.
Save the on-off state
Use Boolean attributes LIT Save "on" or "off", and default to false.
Process player right click
Rewrite use Method: The server switches state and plays the lever click sound at the same time.
Connect Appearance to Data
Added block state, two models, name, drop table and workbench crafting recipe.
/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.
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.jsonblock 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.
lit=falseLight level 0use() + !LITlit=trueLight level 15boolean willBeLit = !state.getValue(LIT);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.
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());
}
}Statement LIT
BooleanProperty There are only two values, true and false, which just represent the light switch.
Set default status
The newly placed block defaults to lit=falseSo it doesn't glow at first.
Add attributes to state definition
It's missing. builder.add(LIT) Property errors occur when starting or placing blocks.
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 com.example.examplemod.block.RightClickLightBlock;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
// 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);
}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.
{
"variants": {
"lit=false": {
"model": "examplemod:block/right_click_light_block_off"
},
"lit=true": {
"model": "examplemod:block/right_click_light_block_on"
}
}
}{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "minecraft:block/redstone_lamp"
}
}{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "minecraft:block/redstone_lamp_on"
}
}{
"parent": "examplemod:block/right_click_light_block_off"
}Add Chinese and English names
"block.examplemod.right_click_light_block":
"右键发光方块""block.examplemod.right_click_light_block":
"Right-click Light Block"Drop itself after destruction
{
"type": "minecraft:block",
"pools": [{
"rolls": 1,
"entries": [{
"type": "minecraft:item",
"name": "examplemod:right_click_light_block"
}],
"conditions": [{
"condition": "minecraft:survives_explosion"
}]
}]
}Add workbench recipe
{
"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.
Fast compilation
.\gradlew.bat compileJava processResourcesStart development client
.\gradlew.bat runClientGet the squares and cut them to the night.
/give @s examplemod:right_click_light_block
/time set midnightExtinguishes when put down
The appearance is that the redstone lamp is unlit and there is no additional lighting around it.
Light up after right-clicking
The appearance brightens, 15 levels of light appear around it, and a click sound is heard.
Right click again to turn off
Description LIT can move from false to true, and then return to false.
Re-entering the world.
The block still maintains the state before leaving, indicating that BlockState is saved.
Dropped after destruction
Blocks will drop the same re-placeable block item.
Formula Available
Eight fluorite powder surrounding a redstone lamp can be used to synthesize new blocks.
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.
| Phenomenon | Most likely cause | Inspection method |
|---|---|---|
| The attribute does not exist when starting | Forget builder.add(LIT) | Confirm that attributes are both declared and state definitions are added. |
/give Prompt unknown items | The registered name is different, or the BlockItem is not registered | Full text search right_click_light_blockAnd that's exactly the same thing. |
| Display purple and black grid | Model path or JSON syntax error | In latest.log Search Unable to load model. |
| The right button changes but does not emit light. | lightLevel Same LIT not read | Confirm expression returns 15 or 0. |
| No response when right-clicking | The item in hand preempts the interaction, or only changes the status on the client | Test empty-handed first; confirm server call setBlock. |
| No falling after destruction | The drop table is missing or the directory is wrong | Confirm that the path is data/examplemod/loot_tables/blocks. |
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.
Lower Brightness
Change the lighting brightness from 15 to 8 and compare the lighting range at night.
Change sound
Try SoundEvents.AMETHYST_BLOCK_CHIME.
Only empty hands allowed
Check player.getItemInHand(hand).isEmpty().
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.