用户:MashKJo/1.12.2模组开发教程/10.BlockState系统及Forge BlockStates V1模型格式:修订间差异

无编辑摘要
无编辑摘要
 
第5行: 第5行:
原版中有很多多BlockState的方块,如熔炉有4种方块状态——朝向有4种:水平方向的东、南、西、北,而实际上熔炉的燃烧/熄灭这一属性不是通过IProperty控制的,而是通过构造方法中的一个boolean参数控制的——即熄灭的熔炉和燃烧的熔炉实际上不是同一个Block,而它们各自有4种方块状态。
原版中有很多多BlockState的方块,如熔炉有4种方块状态——朝向有4种:水平方向的东、南、西、北,而实际上熔炉的燃烧/熄灭这一属性不是通过IProperty控制的,而是通过构造方法中的一个boolean参数控制的——即熄灭的熔炉和燃烧的熔炉实际上不是同一个Block,而它们各自有4种方块状态。


在本节教程中,笔者将完整地讲述创建一个多BlockState方块的全过程。
在本节教程中,作者将完整地讲述创建一个多BlockState方块的全过程。


== 给方块附加属性 ==
== 给方块附加属性 ==
第39行: 第39行:
那么,工作是不是已经做完了呢?当然没有,我们毕竟还要写相应的JSON文件嘛,不过读者可能会觉得,仅仅是为了测试的话,没必要立刻就写JSON文件,可以直接顶着紫黑块的压力,按F3查看它的属性值!好的,这么做确实可以,然而注册完方块,runClient之后读者会发现代码根本跑不起来,会崩溃——且抛出一个IllegalArgumentException:"Don't know how to convert [state] back into data..."。
那么,工作是不是已经做完了呢?当然没有,我们毕竟还要写相应的JSON文件嘛,不过读者可能会觉得,仅仅是为了测试的话,没必要立刻就写JSON文件,可以直接顶着紫黑块的压力,按F3查看它的属性值!好的,这么做确实可以,然而注册完方块,runClient之后读者会发现代码根本跑不起来,会崩溃——且抛出一个IllegalArgumentException:"Don't know how to convert [state] back into data..."。


好的,所以笔者还需要讲一个很重要的概念:方块的meta值。是不是很眼熟?ItemStack就有meta值啊。只是在ItemStack中,meta值兼任损害值和类型序数两个概念,由hasSubtypes字段控制它的具体含义。但对于方块而言,没损害值这一说,所以方块的meta值就代表它的一个类型。这么说,方块的meta岂不是和它的BlockState作用重合了?是这样的,在Minecraft 1.8版本之前,BlockState系统还不存在,那时候方块被附加上不同属性后得到的“状态”就是用方块的meta值来描述的——玩家在世界中和方块交互时,以及Minecraft内部机制序列化、反序列化地图时,用的都是方块的meta值。但BlockState系统加入后,meta值便只被用于序列化、反序列化存档地图了。显然我们需要给一个方块的所有BlockState都各自指定一个meta值,否则Minecraft根本就不知道如何序列化或反序列化这种多BlockState方块。我们覆写<code>Block#getStateFromMeta</code>和<code>Block#getMetaFromState</code>这两个方法,即可,runClient后,游戏便能正常进入了。
好的,所以作者还需要讲一个很重要的概念:方块的meta值。是不是很眼熟?ItemStack就有meta值啊。只是在ItemStack中,meta值兼任损害值和类型序数两个概念,由hasSubtypes字段控制它的具体含义。但对于方块而言,没损害值这一说,所以方块的meta值就代表它的一个类型。这么说,方块的meta岂不是和它的BlockState作用重合了?是这样的,在Minecraft 1.8版本之前,BlockState系统还不存在,那时候方块被附加上不同属性后得到的“状态”就是用方块的meta值来描述的——玩家在世界中和方块交互时,以及Minecraft内部机制序列化、反序列化地图时,用的都是方块的meta值。但BlockState系统加入后,meta值便只被用于序列化、反序列化存档地图了。显然我们需要给一个方块的所有BlockState都各自指定一个meta值,否则Minecraft根本就不知道如何序列化或反序列化这种多BlockState方块。我们覆写<code>Block#getStateFromMeta</code>和<code>Block#getMetaFromState</code>这两个方法,即可,runClient后,游戏便能正常进入了。


和ItemStack不同,方块的meta值只能是0 - 15这个范围内的整数——最多只有16种可能;而在99%的情况下,所有BlockState和所有meta值之间的关系都是一一对应的,因此'''通常情况下''',一个方块的BlockState最多只有16种。但也有例外——比如栅栏、红石粉、火焰这些方块,它们实际上有着成百上千种BlockState,那么这是如何做到的呢?它们实际上都只指定了部分BlockState的meta值,同时覆写了<code>Block#getActualState</code>方法,该方法能根据周围的方块的方块状态,计算出它本身该是什么方块,这一部分算出来的BlockState实际上是不参与序列化和反序列化的。这个手段实际上很有局限性,为何?能这么做的方块,它的特点也很明确:它本身的BlockState确实会随着它周围的方块的BlockState的变化而变化,那对于箱子这种能存储物品(实际上是ItemStack)的方块呢?就没辙了,毕竟你总不可能不打开箱子,根据它周围的方块状态就确定它里面装的到底都有啥吧(笑),而且因为ItemStack本身有附加NBT,因此可以这么说,同一种物品的ItemStack有无限种可能。所以,指望着BlockState系统来完成这件事是没辙了。
和ItemStack不同,方块的meta值只能是0 - 15这个范围内的整数——最多只有16种可能;而在99%的情况下,所有BlockState和所有meta值之间的关系都是一一对应的,因此'''通常情况下''',一个方块的BlockState最多只有16种。但也有例外——比如栅栏、红石粉、火焰这些方块,它们实际上有着成百上千种BlockState,那么这是如何做到的呢?它们实际上都只指定了部分BlockState的meta值,同时覆写了<code>Block#getActualState</code>方法,该方法能根据周围的方块的方块状态,计算出它本身该是什么方块,这一部分算出来的BlockState实际上是不参与序列化和反序列化的。这个手段实际上很有局限性,为何?能这么做的方块,它的特点也很明确:它本身的BlockState确实会随着它周围的方块的BlockState的变化而变化,那对于箱子这种能存储物品(实际上是ItemStack)的方块呢?就没辙了,毕竟你总不可能不打开箱子,根据它周围的方块状态就确定它里面装的到底都有啥吧(笑),而且因为ItemStack本身有附加NBT,因此可以这么说,同一种物品的ItemStack有无限种可能。所以,指望着BlockState系统来完成这件事是没辙了。
行政员、​优秀编辑者、​界面管理员、​监督员、​管理员、​小部件编辑者
3,441

个编辑