User Tools

Site Tools


← Go back to the homepage

Fabric Tutorials



These pages are essential must-reads when modding with Fabric, and modding Minecraft in general, if you are new to modding, it is recommended you read the following.


Blocks and Block Entities

Data Generation

World Generation


These pages will guide you through Mojang's Brigadier library which allows you to create commands with complex arguments and actions.


These pages will guide you through using the many events included in Fabric API, and how to create your own events for you or other mods to use.



Mixins & ASM

These pages will guide you through the usage of SpongePowered's Mixin library, which is a highly complex topic. We recommend you read these pages thoroughly.



Contribute to Fabric


Make a Block Waterloggable

To make blocks waterloggable, implement Waterloggable interface and override some methods.

public class VerticalSlabBlock extends HorizontalFacingBlock implements Waterloggable {

In this case, we store the Properties.WATERLOGGED as a static field in this class, and you can use WATERLOGGED to access the field. (Unnecessary as it looks, most vanilla Minecraft block classes do that, so we do as well. Of course you can refuse to do that, and use Properties.WATERLOGGED every time to access it, or just directly import the static field.) We have to manually make the block recognize the property, as it is not done for you by Waterloggable interface.

    // Note the ''Properties'' is Don't import the wrong one.
    public static final BooleanProperty WATERLOGGED = Properties.WATERLOGGED;
    // Let default value of the WATERLOGGED property become ``false``
    public VerticalSlabBlock(Settings settings) {
            .with(Properties.HORIZONTAL_FACING, Direction.NORTH)
            .with(WATERLOGGED, false);
    // Make the block recognize the property, otherwise setting the property will through exceptions.
    protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
        builder.add(Properties.HORIZONTAL_FACING, WATERLOGGED);

We also have to override getPlacementState, so that the block placed in water is initially waterlogged.

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

Override getFluidState so that when it is waterlogged the block displays water.

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

Override getStateForNeighborUpdate so that it correctly handles the flowing of water.

    public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) {
        if (state.get(WATERLOGGED)) {
            // This is for 1.17 and below: world.getFluidTickScheduler().schedule(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
            world.scheduleFluidTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
        return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos);

Now the block becomes waterloggable, and works correctly with water.

tutorial/waterloggable.txt · Last modified: 2022/12/16 02:12 by solidblock