方块朝向 1.21.1 NeoForge 长线教程计划
本篇教程的视频
本篇教程的源代码
GitHub地址:
查看源代码
那么在我们的游戏中,除了六个面都是相同材质的方块之外,大多数方块都是有朝向的
比如熔炉,我暂且将它开口的那个面称之为特征面
当我们放下熔炉方块时,不论你面朝何方(除了上下),熔炉的特征面永远是面向玩家的
同理,楼梯、讲台、床、门这种异形方块也都是有朝向的
FACING属性
这里我们就来看看熔炉方块的源代码,重点找到它的方块状态,这里找到AbstractFurnaceBlock类
1 | public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING; |
这里定义了一个FACING属性,从它的名字来看就是我们要找的方块朝向
这个是一个DirectionProperty类型的变量,是Minecraft中用于表示方位的属性
1 | public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; |
虽然说熔炉方块的FACING引用的是HorizontalDirectionalBlock中的,不过它本质上引用的是BlockStateProperties.HORIZONTAL_FACING
在BlockStateProperties类中,我们可以找到它的定义
1 | public static final DirectionProperty HORIZONTAL_FACING = DirectionProperty.create("facing", Direction.Plane.HORIZONTAL); |
另外我们也可以看到另一个名为FACING这个属性的定义
1 | public static final DirectionProperty FACING = DirectionProperty.create( |
原版就只有木桶方块引用的是这个FACING,相比较而言,HORIZONTAL_FACING这个属性只有东西南北四个方向,而FACING则多了上下
哎?那么楼梯的上下是怎么区分的?好问题
楼梯方块有其他的方块状态共同决定其形状,它的方法也和其他方块不一样
具体的感兴趣的同学可以自己研究,未来我们或许会讲讲楼梯方块的具体实现
状态初始化
另外在熔炉方块的构造函数中,我们可以看到对方块状态初始化
1 | protected AbstractFurnaceBlock(BlockBehaviour.Properties properties) { |
这里我们看到了FACING,并且初始化为Direction.NORTH,也就是朝北
另外一个LIT属性我们在未来的教程中也会讲,这个是控制方块发光的属性,因为熔炉在工作时,它会照亮周围
一些方法
然后,我们再看看引用FACING的一些方法
1 |
|
这里我们看到了getStateForPlacement这个方法,这个方法用于获取方块放置时的状态
getHorizontalDirection这个方法用于获取玩家放置方块时的朝向
getOpposite方法用于获取方位的反方向,比如玩家面朝南,那么熔炉就会朝北
1 |
|
rotate这个方法用于旋转方块,这里我们直接将FACING属性旋转即可
1 |
|
mirror这个方法用于镜像方块,这里我们直接将FACING属性旋转即可
当然这两个方法具体我也不太清楚是用来干什么的,带有方块朝向的方块,一般都会重写这两个方法
1 |
|
最后还要将方块属性加入到方块中,不然方块还是没有这些属性的
添加朝向
这期教程我们也是用Blockbench制作的方块
导出方块碰撞箱
那么在导出方块之前,我们再安装一个插件,用于导出方块的碰撞箱
在文件->插件中搜索并安装Mod Utils这个插件,然后我们在导出这就会多了一个选项,Export VoxelShape(1.14+ Moded Minecraft)

但在导出之前,还得将我们方块(组成方块的小体块)放到一个名为VoxelShapes这个组下面,这样才能被这个插件识别(感觉这插件要求还挺多)

然后再点击Export VoxelShape(1.14+ Modded Minecraft),就会弹出一个窗口,然后就可以选择映射,这里我们要选择Yarn,导出当前方块的碰撞箱

但这还没完,因为我们需要4个不同面向的方块碰撞箱,那么现在你想到,把方块整体转一下呗
哎,在你的方块中没有斜着的体块时可以这么做,但是,本期教程的案例是我从方舟模组中拿过来的一个时钟(见视频教程),
这里面有很多斜着的小体块,当我们整体旋转时,斜着的小体块就跑掉了

因为由于Blockbench的限制,Java版的方块只支持单轴旋转
那么怎么办呢?这个倒是简单,直接做一个能够覆盖整个方块的体块,然后将其他的体块删了,再导出方块的碰撞箱,
如此导出其他3个碰撞箱

另外注意,在旋转方块时,将枢轴点调整到一个完整方块的中心,即X和Z调到8,Y轴可以不管
SimpleOrangeClock
这里我们新建一个自定义的方块类,SimpleOrangeClock,继承Block类
1 | public class SimpleOrangeClock extends Block { |
方块状态
接下来我们来设置这个方块的方块状态
首先引入FACING这个参数
1 | public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING; |
这里我们可以直接引用BlockStateProperties.HORIZONTAL_FACING
碰撞箱
随后我们将导出的方块碰撞箱放到方块中来
1 | private static final VoxelShape SHAPE_N = Block.box(3, 3, 15, 13, 13, 16); |
一共是4个方位的不同碰撞箱
方块状态初始化
构造函数中的方块状态初始化写一下
1 | this.registerDefaultState(this.defaultBlockState().setValue(FACING, Direction.NORTH)); |
和原版一样,初始化为朝北
后面我们就要重写一些方法了
getShape
1 |
|
重写getShape这个方法,这个方法用于获取方块的碰撞箱
因为FACING的实际属性是一个枚举类型的(你一路挖下去就能发现),所以这里可以直接用switch来判断当前方块面向并返回对应的碰撞箱
哎,这里就有人要问了,FACING不是DirectionProperty吗,怎么就成枚举了?
其实原版大多数的方块状态都是一个注册id再带上一个枚举类型的变量,后面我们自己来定义方块状态属性时,你可能就能理解了
这里的FACING属性,其实就是一个facing的注册id,带上一个有东西南北这4个不同面向的方块属性
createBlockStateDefinition
1 |
|
别忘了将FACING属性加入到方块中
其他的
1 |
|
另外的三个我们就不再赘述了,按照原版来写就好了
注册方块
注册方块
1 | public static final DeferredBlock<SimpleOrangeClock> SIMPLE_ORANGE_CLOCK = |
实例化SimpleOrangeClock
添加物品栏
1 | output.accept(ModBlocks.SIMPLE_ORANGE_CLOCK); |
不要忘了物品栏
数据生成
语言文件
1 | add(ModBlocks.SIMPLE_ORANGE_CLOCK.get(), "Simple Orange Clock"); |
模型文件
1 | customHorizontalBlock(ModBlocks.SIMPLE_ORANGE_CLOCK); |
方块状态文件,这里我们用到了customHorizontalBlock自定义的方法来生成默认面向北的方块状态文件
当然,这个并不会生成我们的方块模型文件,我们使用Blockbench制作的模型文件
测试
那么最后,我们就可以进入游戏进行测试了





