由于网上找到的 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
位置的方块标记为需要重新渲染