让方块可含水

要让方块可含水,实现 Waterloggable 接口并覆盖一些方法。

public class VerticalSlabBlock extends HorizontalFacingBlock implements Waterloggable {
    [...]
}

在本例中,我们将 Properties.WATERLOGGED 存储为类中的静态字段,然后你可以直接使用 WATERLOGGED 来访问这个字段。(虽然不必要,但是大多数 Minecraft 原版的方块类都是这么做的,所以我们也这么做。当然你也可以不这么做,然后每次使用 Properties.WATERLOGGED 来访问,或者直接导入静态字段。)我们需要手动让方块认识这个属性,因为 Waterloggable 接口并没有自动为你完成这些。

    // 注意 ''Properties'' 是 net.minecraft.state.property.Properties,别导入错了。
    public static final BooleanProperty WATERLOGGED = Properties.WATERLOGGED;
 
    // 将 WATERLOGGED 属性的默认值设为 ``false``
    public VerticalSlabBlock(Settings settings) {
        super(settings);
        setDefaultState(getDefaultState()
            .with(Properties.HORIZONTAL_FACING, Direction.NORTH)
            .with(WATERLOGGED, false));
    }
 
    // 让方块认识这个属性,否则设置该属性将会抛出异常。
    @Override
    protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
        builder.add(Properties.HORIZONTAL_FACING, WATERLOGGED);
    }

我们还需要覆盖 getPlacementState,这样放在水中的方块就会一开始就含水。

    @Override
    public BlockState getPlacementState(ItemPlacementContext ctx) {
        return this.getDefaultState()
            .with(Properties.HORIZONTAL_FACING, ctx.getHorizontalPlayerFacing().getOpposite())
            .with(WATERLOGGED, ctx.getWorld().getFluidState(ctx.getBlockPos()).getFluid() == Fluids.WATER);
    }

覆盖 getFluidState,这样方块含水后就会显示水。

    @Override
    public FluidState getFluidState(BlockState state) {
        return state.get(WATERLOGGED) ? Fluids.WATER.getStill(false) : super.getFluidState(state);
    }

覆盖 getStateForNeighborUpdate,以正确地处理水流。

1.21.2 之前的版本,请这么写:

    @Override
    public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) {
        if (state.get(WATERLOGGED)) {
            // 对于 1.17 以及更低的版本:
            // world.getFluidTickScheduler().schedule(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
            // 对于 1.18 之后、1.21.2 之前的版本:
            world.scheduleFluidTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
        }
 
        return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos);
    }

1.21.2 以及更高的版本,请这么写:

    @Override
    public BlockState getStateForNeighborUpdate(BlockState state, WorldView world, ScheduledTickView tickView, BlockPos pos, Direction direction, BlockPos neighborPos, BlockState neighborState, Random random) {
        if (state.get(WATERLOGGED)) {
            // For versions since 1.21.2:
            tickView.scheduleFluidTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
        }
 
        return super.getStateForNeighborUpdate(state, world, tickView, pos, direction, neighborPos, neighborState, random);
    }

现在方块可含水了,并且与水有关的功能都能正常运作。