Minecraft 1.8 Forge API BlockState 与红石详解

由于网上找到的 Minecraft Forge 文档实在是少的可怜,我决定自己写一份以防未来的自己忘记。具体的实践可以在我的客运铁路 mod 见到。

红石的更新本质上也是方块更新,因此当一个方块想要检测红石信号,处理的代码应当放在 Block 类的 onNeighborBlockChange(World worldIn, BlockPos pos, IBlockState state, Block neighborBlock) 方法。

BlockStateIBlockState

可以在方块的 Class 建立 BlockState 以允许方块拥有不同的状态 (IProperty),不同的状态可以在 assets/<MODID>/blockstates/<block_instance_name>.json 中定义不同的方块模型。

每一个 IProperty 拥有自己的 name 和可以取到的有限个值,这些值在 Java 内部以 enum 的形式实现。关于 enum 变量类型,可以在王八壳的 javadoc 上找到。

一个方块的 BlockState 可以包含一个或多个 IProperty,可以使用已经定义好的 IProperty 子类(PropertyDirection, PropertyBool)也可以自己定义 enum 建立 PropertyEnum

Class: public CustomBlock extends Block

通过以下方式建立 IProperty 及其子类的实例:

  • public static final PropertyDirection FACING = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL);
    建立新的方向属性,名称为 "facing" ,可以取的值为平面方向的朝向,为 EnumFacing 下的 NORTHEASTSOUTHWEST
  • public static final PropertyBool POWERED = PropertyBool.create("powered");
    建立布尔型只能为 truefalse 的方块属性。

如果一上的满足不了你或者想要自己的 Property 类型,你需要自定义 enum。比如以下例子,EnumPresident 包含 "donaldtrump""hillaryclinton"。这样就定义了一个 IProperty,这个 Property 只能取川普和克林顿两个值,然后你就可以根据不同的值给 Block 上川普或者克林顿的贴图

  • public static final PropertyEnum PRESIDENT = PropertyEnum.create("president", CustomBlock.EnumPresident.class);

Method: public int getMetaFromState(IBlockState state)
Method: public IBloockState getStateFromMeta(int meta)

meta 是实际上存在于 Minecraft 内部并存储到磁盘的数据,取值范围为 [0, 15],

有个坑,如果想要方块根据红石状态改变模型,需要在 getMetaFromState() 方法和 getStateFromMeta() 方法中实现将 POWERED 属性编码到 meta 和从 meta 恢复。

Method: public IBlockState getActualState(IBlockState state, IBlockAccess worldIn, BlockPos pos)

无需存在于 meta 中的静态且可以通过周围方块推断得到的属性(栅栏的连接,屏蔽门上下两半的判断)应当在此方法中获取,这里的静态自然不包含红石更新带来的变化。此方法应当返回 state.withProperty(IProperty type, Comparable value) 返回的新 IBlockState

Method: public void onNeighborBlockChange(World worldIn, BlockPos pos, IBlockState state, Block neighborBlock)

是当某方块周围被添加、敲掉了方块、红石激活、附近方块的 BlockState 改变时被调用的方法

  • worldIn
    要处理的 Minecraft 世界
  • pos
    CustomBlock 自身所在的位置
  • state
    CustomBlock 当前的状态
  • neighborBlock
    触发自身方块更新事件的相邻方块

在此处可以做的事情有:

  • boolean World.isBlockPowered(BlockPos pos)
    检查处于 pos 位置的方块是否被红石充能
  • Comparable state.getValue(EnumProperty)
    获取自身的方块状态中的某属性值以便处理
  • IBlockState World.getBlockState(BlockPos pos)
    获取处于 pos 位置的方块的方块状态实例,可以继续加上 getValue() 获取属性值或者 getBlock() 获得方块以检测是否为某些特定方块
  • void World.setBlockToAir(BlockPos pos)
    pos 位置的方块强行替换成空气,不会掉落物品。
  • void World.markBlockForUpdate(BlockPos pos)
    把处于 pos 位置的方块标记为需要重新渲染

Leave a Reply

Your email address will not be published. Required fields are marked *