1. 自定义方块状态映射方式

考虑以下几个情况:

  • 我的方块有若干方块状态,但所有方块状态的外观都是一致的(即只有一个模型)。如此一来,我仍然需要把这些属性对应的情况都列出来。有没有办法做到省略不写?
  • 出于某种原因,我希望 BlockState json 和 model json 可以一一对应,能否做到?
  • 出于某种原因,我想让某个特定方块状态使用的模型来自另一个 block state json。能否做到?

Minecraft 它本身也遇到了这样的奇怪需求,因此 IStateMapper 应运而生。它用于指定 IBlockStateModelResourceLocation 之间的对应关系。在 Minecraft 1.12 中,所有的 Block 都有一个默认的 IStateMapper 实现,这个默认的实现也直接决定了原版的 BlockState json 的格式是这样的:

{
    "variants": {
        "facing=west": { "model": "..." },
        "facing=east": { "model": "..." },
        "facing=north": { "model": "..." },
        "facing=south": { "model": "..." }
    }
}

1.1. BlockStateMapper.registerBlockStateMapper

你需要通过 BlockStateMapper.registerBlockStateMapperfunc_178447_a)来注册你自己的 IStateMapper 实现。

BlockStateMapper.registerBlockStateMapper(ModBlocks.myBlock, block -> {
    // 返回值为 Map<IBlockState, ModelResourceLocation>。
    // 所以每一个可能的 IBlockState 都应对应一个 ModelResourceLocation。
    return ...;
})

1.2. 现成的实现:StateMap

但是要手动构造一个包含所有可能性的 Map<IBlockState, ModelResourceLocation> 显得太过麻烦了。Minecraft 自己便有这样一个工具类可以快速解决一些简单的映射关系。

BlockStateMapper.registerBlockStateMapper(ModBlocks.myBlock,
    new StateMap.Builder().ignore(...).withName(...).withSuffix("...").build());

其中:

  • ignore 用于忽略指定的 IProperty
  • withName 的效果是根据 IProperty 的值把一个 BlockState json 展开成多个。举例,如果有一个方块叫 machine,有 TYPE 属性,其值可以是 MACHINE_A, MACHINE_BMACHINE_C,那么 withName(TYPE) 会令 Minecraft 尝试寻找下面三个 BlockState json 而不是 machine.json 下的 type=machine_a 这样的 variant:
    • machine_a.json
    • machine_b.json
    • machine_c.json
  • withSuffix 会在原有的 ModelResourceLocationlocation 基础上加一个后缀。

1.3. 现成的半成品:StateMapperBase

与此同时,Minecraft 还有一个 StateMapperBase 可以简化 IStateMapper 的实现。
StateMapperBase 是个抽象类,它没有实现的方法叫 getModelResourceLocationfunc_178132_a)——它接受一个 IBlockState 并返回对应的 ModelResourceLocation

BlockStateMapper.registerBlockStateMapper(ModBlocks.myBlock, new StateMapperBase() {
    @Override
    protected ModelResourceLocation getModelResourceLocation(@Nonnull IBlockState state) {
        // 是不是比 IStateMapper 更符合直觉了?
        return new ModelResourceLocation(new ResourceLocation("my_mod", ...), ...);
    }
});

这个类经常用在处理流体方块的方块状态与模型之间的映射上,在第二十七章的有关章节会再次提到。