Uploaded image for project: 'Minecraft: Java Edition'
  1. Minecraft: Java Edition
  2. MC-120986

Comparators do not update correctly in some cases



    • Type: Bug
    • Status: Open
    • Resolution: Unresolved
    • Affects Version/s: Minecraft 1.12.1, Minecraft 1.12.2 Pre-Release 1, Minecraft 1.12.2 Pre-Release 2, Minecraft 1.12.2, Minecraft 17w43a, Minecraft 17w43b, Minecraft 17w45b, Minecraft 17w46a, Minecraft 17w47a, Minecraft 17w47b, Minecraft 17w48a, Minecraft 17w49a, Minecraft 17w49b, Minecraft 17w50a, Minecraft 18w03b, Minecraft 18w05a, Minecraft 1.13-pre3, Minecraft 1.13-pre6, Minecraft 1.13-pre7, Minecraft 1.13, Minecraft 1.13.1, Minecraft 1.13.2, Minecraft 19w03b, Minecraft 19w03c, Minecraft 19w04b, Minecraft 19w05a, Minecraft 19w06a, Minecraft 1.14, 1.14.4, 1.15 Pre-release 1, 1.15.2, 20w09a, 20w19a, 20w21a, 1.16 Release Candidate 1, 1.16, 1.16.1, 1.16.4 Pre-release 2, 20w45a, 20w51a, 21w03a, 1.16.5, 21w07a
    • Fix Version/s: None
    • Confirmation Status:
    • Category:
    • Mojang Priority:


      This is a compilation of instances were comparators do not update their power level correctly when a block with a comparator input override changed.

      Affected blocks

      • beehive / bee nest
        • placed (behind block)
        • broken (behind block)
      • brewing stand
        • placed (behind block) using command /setblock x y z brewing_stand{Items:[{Slot:0b,id:"potion",Count:1b}]}
        • broken (behind block)
      • cake
        • placed (behind block) using command /setblock x y z cake (Does update if placed manually)
        • broken (behind block)
        • completely eaten up (behind block)
      • cauldron
        • placed (behind block) using command /setblock x y z cauldron[level=3]
        • removed (behind block)
        • filled by rain
      • chest
        • placed (behind block) using command /setblock x y z chest{Items:[{Slot:0b,id:"stone",Count:1b}]}
      • command block
        • placed (behind block) using command /setblock x y z command_block{SuccessCount:1}
        • broken (behind block)
      • compost
        • removed (behind block)
      • detector rail
        • broken (behind block)
      • dispenser
        • placed (behind block) using command /setblock x y z dispenser{Items:[{Slot:0b,id:"stone",Count:1b}]}
      • dropper
        • placed (behind block) using command /setblock x y z dropper{Items:[{Slot:0b,id:"stone",Count:1b}]}
      • end portal frame
        • placed (behind block) using command /setblock x y z end_portal_frame[eye=true]
        • broken (behind block)
      • furnace
        • placed (behind block) using command /setblock x y z furnace{Items:[{Slot:0b,id:"iron_ore",Count:1b}]}
      • hopper
        • placed (behind block) using command /setblock x y z hopper{Items:[{Slot:0b,id:"stone",Count:1b}]}
      • item frame
        • broken (by piston or command, left click would first remove the item)
        • In case MC-45619 is intended: If a block inside of the item frame is removed
      • jukebox
        • broken (behind block)
      • respawn anchors
        • explodes (behind block)
      • sculk sensors
      • (behind block): The comparator must detect the affected block through a solid block to not update in the described situation.
      • placed: Comparator does not update when the affected block is placed.
      • broken: Comparator does not update when the affected block is broken. Also applies for being moved away by a piston.
      • changed: Comparator does not update when the affected block changes its comparator input override.

      Here is a video with a few examples when this bug happens. Note that it doesn't make any difference whether a block is moved by a piston or removed by a player. Some blocks however cannot be moved by pistons.

      That's every block and issue I could find related to this. If I missed something, please let me know down below.

      Code Analysis

      This is based on a decompiled version of Minecraft 1.12 using mcp 980.

      Breaking/Moving block

      In net.minecraft.world.World.setBlockState(BlockPos, IBlockState, int) there is some code that is meant to update comparators when a block with a comparator input override is placed and the flag for block updates is set. In there, you could also cause updates if a block with comparator input override is removed, however there are some cases where the update flag is not set and instead the net.minecraft.world.World.notifyNeighborsOfStateChange(BlockPos, Block, boolean) method is called instead.
      So my proposed fix would be to remove the following

      net.minecraft.world.World.setBlockState(BlockPos, IBlockState, int)
      if (!this.isRemote && (flags & 1) != 0)
          this.notifyNeighborsRespectDebug(pos, iblockstate.getBlock(), true);
          //remove this
          if (newState.hasComparatorInputOverride())
              this.updateComparatorOutputLevel(pos, block);

      and instead add this to net.minecraft.world.World.notifyNeighborsOfStateChange(BlockPos, Block, boolean)

      net.minecraft.world.World.notifyNeighborsOfStateChange(BlockPos, Block, boolean)
      IBlockState newState = getBlockState(pos);
      if(blockType.getDefaultState().hasComparatorInputOverride() || newState.hasComparatorInputOverride())
      	updateComparatorOutputLevel(pos, newState.getBlock());

      Some code that becomes redundant after applying that fix also should be removed. That would be to remove worldIn.updateComparatorOutputLevel(pos, this); :in the following methodes

      • net.minecraft.block.BlockChest.breakBlock(World, BlockPos, IBlockState)
      • net.minecraft.block.BlockDispenser.breakBlock(World, BlockPos, IBlockState)
      • net.minecraft.block.BlockFurnace.breakBlock(World, BlockPos, IBlockState)
      • net.minecraft.block.BlockHopper.breakBlock(World, BlockPos, IBlockState)
      • net.minecraft.block.BlockShulkerBox.breakBlock(World, BlockPos, IBlockState)

      An alternative would be to override the net.minecraft.block.Block.breakBlock(World, BlockPos, IBlockState) in all the classes that have a comparator input override as proposed by [Mod] Marcono1234 in this comment. But it might be cleaner to apply the fix above since you don't need to remember to override the method when adding a new block with a comparator override.

      Another alternative might be to add a class that all blocks with a comparator input override need to extend in which the net.minecraft.block.Block.breakBlock(World, BlockPos, IBlockState) method is already overridden.

      Cauldron being filled by rain

      Code analysis by [Mod] Marcono1234 can be found in this comment


          Issue Links



              Unassigned Unassigned
              Schortan [Mod] NeunEinser
              51 Vote for this issue
              27 Start watching this issue