mojira.dev
MC-297032

Placing a hopper in a powered location does not update adjacent flowing water/lava

This issue was introduced in 17w47a.

  1. Build waterways

  2. Power a certain area of the waterway with redstone

  3. Place the hopper at the powered location

  4. The water flow was not intercepted as expected

Attachments

Comments 4

Can confirm for 18w19a

Hoppers don’t send block updates at all when placed (they do send shape updates (observer update))!

Very annoying bug for survival playstyle. Please do fix!

This is very strange. Placing a hopper in a powered location doesn’t update adjacent flowing water, but in all other cases hopper placement seems to work as expected.

Lava is not updated by this hopper as well.

This occurs in 1.21.11, demonstrated below:

A potential cause for this behavior can be found in HopperBlock.class and its onPlace and checkPoweredState methods:

   @Override
   protected void onPlace(final BlockState state, final Level level, final BlockPos pos, final BlockState oldState, final boolean movedByPiston) {
      if (!oldState.is(state.getBlock())) {
         this.checkPoweredState(level, pos, state);
      }
   }
   private void checkPoweredState(final Level level, final BlockPos pos, final BlockState state) {
      boolean shouldBeOn = !level.hasNeighborSignal(pos);
      if (shouldBeOn != (Boolean)state.getValue(ENABLED)) {
         level.setBlock(pos, state.setValue(ENABLED, shouldBeOn), 2);
      }
   }

When a hopper is powered, the update flag 2 only updates clients, whereas the flag to update the neighboring fluids and blocks is 1. A proposed fix is to change the flag in the level.setBlock line within the checkPoweredState method to a 3 flag.

All of the flags that can be applied to a block can be found within Block.class below:

    public static final int UPDATE_NEIGHBORS = 1;
    public static final int UPDATE_CLIENTS = 2;
    public static final int UPDATE_INVISIBLE = 4;
    public static final int UPDATE_IMMEDIATE = 8;
    public static final int UPDATE_KNOWN_SHAPE = 16;
    public static final int UPDATE_SUPPRESS_DROPS = 32;
    public static final int UPDATE_MOVE_BY_PISTON = 64;
    public static final int UPDATE_SKIP_SHAPE_UPDATE_ON_WIRE = 128;
    public static final int UPDATE_SKIP_BLOCK_ENTITY_SIDEEFFECTS = 256;
    public static final int UPDATE_SKIP_ON_PLACE = 512;
    public static final @Block.UpdateFlags int UPDATE_NONE = 260;
    public static final @Block.UpdateFlags int UPDATE_ALL = 3;
    public static final @Block.UpdateFlags int UPDATE_ALL_IMMEDIATE = 11;
    public static final @Block.UpdateFlags int UPDATE_SKIP_ALL_SIDEEFFECTS = 816;
    public static final float INDESTRUCTIBLE = -1.0F;
    public static final float INSTANT = 0.0F;
    public static final int UPDATE_LIMIT = 512;

Using the 3 flag is a commonly used way to update all neighboring updates (as seen, UPDATE_ALL).

A proposed fix is to change this line:

level.setBlock(pos, state.setValue(ENABLED, shouldBeOn), 2);

to

level.setBlock(pos, state.setValue(ENABLED, shouldBeOn), 3);

because using 3 will ensure that initially powered hoppers will update neighbors (1 or UPDATE_NEIGHBORS + 2 or UPDATE_CLIENTS).

Helvetica_Volubi

(Unassigned)

Confirmed

Platform

Important

Block states

1.21.5, 25w19a, 1.21.11

Retrieved