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

Giving an item on the same tick it's placed causes desync for the item stack

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • None
    • Minecraft 1.12.2, Minecraft 1.13-pre6, Minecraft 1.13, Minecraft 1.13.1, 1.16.3, 1.20.1, 1.20.2 Pre-release 1
    • None
    • Confirmed
    • (Unassigned)

      The Bug:

      When the player is given an item on the same tick that it is placed on, a desync occurs and a visual discrepency can be seen. With an item stack greater of one, the player is given a "ghost item" (an item that exists, but is not visible to the player), and with a stack greater than one the game simply does not update the count.

      Steps to Reproduce:

      (Must be in survival)

      1. Place down a command block, and enter the following command:
        /give @p redstone_block
      1. Place one or more redstone block(s) next to the command block to activate it

      Observed Results:

      The player will properly place down the redstone block, and be given an item, but this will not be properly displayed to the player. Instead, the redstone block will become a "ghost item" that the player cannot see inside their inventory unless they interact with the slot (via placement, moving the item, or dropping it).

      Expected Results:

      The player would be given the redstone block by the command, and this would properly display to the player showing an accurate item stack count.

      Screenshots/Videos:

      Recreating this issue with an item stack of 1:
      2023-09-06_18-12-17.mp4

      Recreating this issue with an item stack greater than 1:
      2023-08-30_22-48-59.mp4

      Code Analysis / Suggested Fix (MCP 1.20.1):

      One possible solution I have been able to find, is to update the players inventory after placing a block. This can be done inside the place() method of BlockItem (net.minecraft.world.item) after checking to see whether or not the player is in creative, and after shrinking the item stack if in survival.

         public InteractionResult place(BlockPlaceContext blockPlaceContext) {
            if (!this.getBlock().isEnabled(blockPlaceContext.getLevel().enabledFeatures())) {
               return InteractionResult.FAIL;
            } else if (!blockPlaceContext.canPlace()) {
               return InteractionResult.FAIL;
            } else {
               BlockPlaceContext blockplacecontext = this.updatePlacementContext(blockPlaceContext);
               if (blockplacecontext == null) {
                  return InteractionResult.FAIL;
               } else {
                  BlockState blockstate = this.getPlacementState(blockplacecontext);
                  if (blockstate == null) {
                     return InteractionResult.FAIL;
                  } else if (!this.placeBlock(blockplacecontext, blockstate)) {
                     return InteractionResult.FAIL;
                  } else {
                     BlockPos blockpos = blockplacecontext.getClickedPos();
                     Level level = blockplacecontext.getLevel();
                     Player player = blockplacecontext.getPlayer();
                     ItemStack itemstack = blockplacecontext.getItemInHand();
                     BlockState blockstate1 = level.getBlockState(blockpos);
                     if (blockstate1.is(blockstate.getBlock())) {
                        blockstate1 = this.updateBlockStateFromTag(blockpos, level, itemstack, blockstate1);
                        this.updateCustomBlockEntityTag(blockpos, level, player, itemstack, blockstate1);
                        blockstate1.getBlock().setPlacedBy(level, blockpos, blockstate1, player, itemstack);
                        if (player instanceof ServerPlayer) {
                           CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer)player, blockpos, itemstack);
                        }
                     }
      
                     SoundType soundtype = blockstate1.getSoundType();
                     level.playSound(player, blockpos, this.getPlaceSound(blockstate1), SoundSource.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F);
                     level.gameEvent(GameEvent.BLOCK_PLACE, blockpos, GameEvent.Context.of(player, blockstate1));
                     if (player == null || !player.getAbilities().instabuild) {
                        itemstack.shrink(1);
      -> FIX START
                        player.containerMenu.broadcastChanges();
      -> FIX END
                     }
      
                     return InteractionResult.sidedSuccess(level.isClientSide);
                  }
               }
            }
         }
      

      This fix provides the following behavior:
      2023-08-30_23-15-56.mp4

      Notes:

      As Kieren Chantrell has pointed out in their comment, this also occurs with functions as well.

            Unassigned Unassigned
            Jingy [Helper] Jiingy
            Votes:
            4 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved:
              CHK: