本篇教程的视频
本篇教程的源代码
GitHub地址:
柱类方块类
这里我们直接来写这个柱类方块,因为我们之前已经写过一个可连接方块了,而这一次写的柱子要比之前的沙发还要简单
之前的沙发判断的是左右,而这一次,我们只要判断上下的方位就好了
ModPillarBlock
创建ModPillarBlock类,继承自Block
1 2 3 4 5
| public class ModPillarBlock extends Block { public ModPillarBlock(Properties pProperties) { super(pProperties); } }
|
方块属性
同样的,我们来写一个方块属性的枚举类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public enum Type implements StringRepresentable { SINGLE("single"), TOP("top"), BOTTOM("bottom"), MIDDLE("middle");
private final String id;
Type(String id) { this.id = id; } @Override public String getSerializedName() { return this.id; } }
|
同样还是实现StringRepresentable这个接口,然后按照之前的写法来写4个不同的状态
声明方块属性
1
| public static final EnumProperty<Type> TYPE = EnumProperty.create("type2", Type.class);
|
因为我们之前在沙发那期教程中,已经注册了一个EnumProperty类型的type,所以这里的注册id要改一下
然后进行方块属性的初始化
1
| this.registerDefaultState(this.defaultBlockState().setValue(TYPE, Type.SINGLE));
|
那么默认就是SINGLE这个状态
还要将方块属性加入到方块中
1 2 3 4
| @Override protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> pBuilder) { pBuilder.add(TYPE); }
|
重写 updateShape 方法
最后我们就要重写方法,改变方块的方块状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Override public BlockState updateShape(BlockState pState, Direction pDirection, BlockState pNeighborState, LevelAccessor pLevel, BlockPos pPos, BlockPos pNeighborPos) { boolean top = pLevel.getBlockState(pPos.above()).is(this); boolean bottom = pLevel.getBlockState(pPos.below()).is(this); if (top && bottom) { return pState.setValue(TYPE, Type.MIDDLE); } else if (top) { return pState.setValue(TYPE, Type.BOTTOM); } else if (bottom) { return pState.setValue(TYPE, Type.TOP); } else { return pState.setValue(TYPE, Type.SINGLE); } }
|
这里我们要重写updateShape方法
两个布尔值分别判断当前方块的上下是否为相同的方块,然后根据这两个布尔值来设置不同的方块状态
好了,这个方块类就这样写完了
其实方块状态能玩出很多花活来,你可以用方块状态来实现很多各种各样的方块,
即便你现在不是很熟练,写得多了,自然就会了
注册方块
注册
注册方块和之前一样,直接注册即可
1 2 3
| public static final RegistryObject<Block> PILLAR = registerBlocks("pillar", () -> new ModPillarBlock(BlockBehaviour.Properties.of().strength(2.0f, 2.0f).noOcclusion()));
|
实例化ModPillarBlock,同样,因为这个是Blockbench制作的非实心方块,所以这里要设置noOcclusion()
物品栏
同样的,我们也要注册物品栏
1
| pOutput.accept(ModBlocks.PILLAR.get());
|
数据文件
战利品列表
1
| dropSelf(ModBlocks.PILLAR.get());
|
常规的战利品列表
语言文件
1
| add(ModBlocks.PILLAR.get(), "Pillar");
|
模型文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| pillar(ModBlocks.PILLAR, "pillar");
private <T extends Block> void pillar(RegistryObject<T> block, String name) { ModelFile modelSingle = models().getExistingFile(modLoc("block/" + name)); ModelFile modelTop = models().getExistingFile(modLoc("block/" + name + "_top")); ModelFile modelBottom = models().getExistingFile(modLoc("block/" + name + "_bottom")); ModelFile modelMiddle = models().getExistingFile(modLoc("block/" + name + "_middle"));
getVariantBuilder(block.get()).forAllStates(state -> { ModPillarBlock.Type type = state.getValue(ModPillarBlock.TYPE);
ModelFile t; switch (type) { case TOP -> t = modelTop; case MIDDLE -> t = modelMiddle; case BOTTOM -> t = modelBottom; default -> t = modelSingle; }
return ConfiguredModel.builder() .modelFile(t) .build(); }); simpleBlockItem(block.get(), modelSingle); }
|
我们修改一下之前的sofa方法,去掉其中的FACING,然后就可以用了
生成的方块状态文件长这样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| { "variants": { "type2=bottom": { "model": "tutorial_mod:block/pillar_bottom" }, "type2=middle": { "model": "tutorial_mod:block/pillar_middle" }, "type2=single": { "model": "tutorial_mod:block/pillar" }, "type2=top": { "model": "tutorial_mod:block/pillar_top" } } }
|
测试
那么最后我们就可以进入游戏进行测试了