-
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)
- Place down a command block, and enter the following command:
/give @p redstone_block
- 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.
- duplicates
-
MC-239935 Client-side desyncs can still occur when using the "/item" or "/give" commands repeatedly
- Open