项目结构
src
├── main
│ ├── java
│ │ ├── com
│ │ │ ├── XXXYJade17
│ │ │ │ └── TestMod
│ │ │ │ ├── Registry.java
│ │ │ │ ├── StateExampleBlock.java
│ │ │ │ └── TestMod.java
│ └── resources
│ ├── assets
│ │ ├── testmod
│ │ │ ├── blockstates
│ │ │ │ └── state_example_block.json
│ │ │ ├── lang
│ │ │ │ ├── en_us.json // 英文语言文件
│ │ │ │ └── zh_cn.json // 中文语言文件
│ │ │ ├── models
│ │ │ │ ├── block
│ │ │ │ │ ├── state_exampe_block_off.json
│ │ │ │ │ └── state_exampe_block_on.json
│ │ │ │ └── item
│ │ │ │ │ └── state_exampe_block.json
│ │ │ └── textures
│ │ │ │ └── block
│ │ │ │ ├── state_exampe_block_off.json.png
│ │ │ │ └── state_exampe_block_on.json.png
一.先创建一个类并且继承Block
public class StateExampleBlock extends Block {
//构造方法
public StateExampleBlock(Properties properties) {
super(properties);
}
}
二.定义需要的状态属性
public static final BooleanProperty LIT = BooleanProperty.create("lit");
- 声明一个布尔型方块状态属性 LIT,表示方块是否处于发光状态。
- BooleanProperty.create("lit") 创建了一个名为 lit 的属性,需要与后续JSON 文件中的 variants 键匹配。
- 除了布尔型还有: DirectionProperty IntegerProperty 等等
三.修改构造函数
public StateExampleBlock(Properties properties) {
super(properties.lightLevel(state -> state.getValue(LIT) ? 15 : 0)); //设置光照等级
this.registerDefaultState(this.stateDefinition.any().setValue(LIT, false)); // 默认状态为未发光
}
- properties.lightLevel(state -> state.getValue(LIT) ? 15 : 0) : 设置lightEmission
- this.registerDefaultState(this.stateDefinition.any().setValue(LIT, false)) : 设置默认值
- 其他可以设置的状态参考Properties类:
private Properties() {
this.soundType = SoundType.STONE;
this.lightEmission = (p_60929_) -> 0;
this.friction = 0.6F;
this.speedFactor = 1.0F;
this.jumpFactor = 1.0F;
this.canOcclude = true;
this.pushReaction = PushReaction.NORMAL;
this.spawnTerrainParticles = true;
this.instrument = NoteBlockInstrument.HARP;
this.isValidSpawn = (p_284893_, p_284894_, p_284895_, p_284896_) -> p_284893_.isFaceSturdy(p_284894_, p_284895_, Direction.UP) && p_284893_.getLightEmission(p_284894_, p_284895_) < 14;
this.isRedstoneConductor = (p_284888_, p_284889_, p_284890_) -> p_284888_.isCollisionShapeFullBlock(p_284889_, p_284890_);
this.isSuffocating = (p_284885_, p_284886_, p_284887_) -> p_284885_.blocksMotion() && p_284885_.isCollisionShapeFullBlock(p_284886_, p_284887_);
this.isViewBlocking = this.isSuffocating;
this.hasPostProcess = (p_60963_, p_60964_, p_60965_) -> false;
this.emissiveRendering = (p_60931_, p_60932_, p_60933_) -> false;
this.requiredFeatures = FeatureFlags.VANILLA_SET;
this.offsetFunction = Optional.empty();
}
四.注册状态
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(LIT);
}
- 注册属性:将 LIT 属性添加到方块状态定义中,这是状态切换的必要步骤。
- Minecraft API 规范:必须通过此方法显式声明所有状态属性,否则状态切换无效
五.创建交互use方法,实现右键点亮方块
@Override
public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if (!level.isClientSide) {
boolean isLit = state.getValue(LIT); //获取当前状态(on|off)
level.setBlock(pos, state.setValue(LIT, !isLit), Block.UPDATE_ALL);
// level.playSound(null, pos, SoundEvents.AMETHYST_BLOCK_HIT, SoundSource.BLOCKS, 1.0F, 1.0F);
}
return InteractionResult.sidedSuccess(level.isClientSide);
}
- level.setBlock(pos, state.setValue(LIT, !isLit), Block.UPDATE_ALL):
setValue : 反转状态
Block.UPDATE_ALL : 上传状态 - (可选) level.playSound(null, pos, SoundEvents.AMETHYST_BLOCK_HIT, SoundSource.BLOCKS, 1.0F, 1.0F) :
播放紫水晶方块被击打的音效
六.添加资源文件
先在BlockState里添加state_example_block.json
{
"variants": {
"lit=false": {
"model": "testmod:block/state_example_block_off"
},
"lit=true": {
"model": "testmod:block/state_example_block_on"
}
}
}
然后根据前面添加Block和BlockItem一样添加对应的json文件即可
*如果原来的方块出现了吞材质的情况,在blockstate里把所有注册的Block都添加一遍就行
默认格式
{
"variants": {
"": {
"model": "testmod:block/example_block_01"
}
}
}
附完整代码
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.BooleanProperty;
import net.minecraft.world.phys.BlockHitResult;
public class StateExampleBlock extends Block {
public static final BooleanProperty LIT = BooleanProperty.create("lit"); // 定义方块状态属性
public StateExampleBlock(Properties properties) {
super(properties.lightLevel(state -> state.getValue(LIT) ? 15 : 0)); // 根据 LIT 属性设置光照
this.registerDefaultState(this.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) {
if (!level.isClientSide) {
boolean isLit = state.getValue(LIT);
level.setBlock(pos, state.setValue(LIT, !isLit), Block.UPDATE_ALL); // 切换发光状态
level.playSound(null, pos, SoundEvents.AMETHYST_BLOCK_HIT, SoundSource.BLOCKS, 1.0F, 1.0F);
}
return InteractionResult.sidedSuccess(level.isClientSide);
}
}