由于网上找到的 Minecraft Forge 文档实在是少的可怜,我决定自己写一份以防未来的自己忘记。具体的实践可以在我的客运铁路 mod 见到。
红石的更新本质上也是方块更新,因此当一个方块想要检测红石信号,处理的代码应当放在 Block 类的 onNeighborBlockChange(World worldIn, BlockPos pos, IBlockState state, Block neighborBlock) 方法。
BlockState 与 IBlockState
可以在方块的 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下的NORTH,EAST,SOUTH,WEST。public static final PropertyBool POWERED = PropertyBool.create("powered");
建立布尔型只能为true或false的方块属性。
如果一上的满足不了你或者想要自己的 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位置的方块标记为需要重新渲染