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

External inventory changes except for the hotbar are not registered in a creative mode item selection screen

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • None
    • 1.20.4, 24w06a, 1.21, 24w33a
    • None
    • Confirmed
    • Inventory, Networking
    • Normal
    • Platform

      External inventory changes (e.g. by picking up items) are not registered on the client if you are in creative mode inventory and are not in the Survival Inventory tab, causing a desync.

      Steps to reproduce:

      1. Fill your hotbar with items.
      2. Go into the creative mode inventory and go to any tab, but the inventory tab (e.g. the search tab).
      3. While in the tab, take any other item and throw it onto the ground.
      4. Wait until you pick it up and observe whether or not the item appears in the inventory.

      Expected behavior:
      The item is picked up and should show up in the inventory.

      Actual behavior:
      The item does not appear in the inventory. However, if you try to remove that particular item, e.g. using /clear @s <item>, the server will report that the item indeed was in the inventory.

      Code analysis:

      net.minecraft.client.multiplayer.ClientPacketListener
      public void handleContainerSetSlot(ClientboundContainerSetSlotPacket packet) {
          // ...
          boolean conditional = false; // Line 1200
      
          if (minecraft.screen instanceof CreativeModeInventoryScreen x) { // Line 1202
              conditional = !x.isInventoryOpen(); // Line 1203
          }
          // 0 means player inventory
          if (packet.getContainerId() == 0 && InventoryMenu.isHotbarSlot(slotId)) {
              // ...
              player.inventoryMenu.setItem(slotId, packet.getStateId(), item);
          } else if (packet.getContainerId() == player.containerMenu.containerId && (packet.getContainerId() != 0 || !conditional)) {
              player.containerMenu.setItem(slotId, packet.getStateId(), item);
          }
      }
      

      This method is responsible for all of the single slot synchronization on the client side.
      Because of it, inventory changes are almost completely ignored if they occur in a non-hotbar slot (first condition) and you are in the creative mode inventory (Line 1202), but not in the "Survival Inventory" tab (Line 1203). (why?)

      Potential fix:
      Just remove those weird conditions. Why do they even exist in the first place?

      public void handleContainerSetSlot(ClientboundContainerSetSlotPacket packet) {
          // ...
          if (packet.getContainerId() == 0) {
              // ...
              player.inventoryMenu.setItem(slotId, packet.getStateId(), item);
          } else if (packet.getContainerId() == player.containerMenu.containerId) {
              player.containerMenu.setItem(slotId, packet.getStateId(), item);
          }
      }
      

      Also, because this is a synchronization step, the client should be able to be confident about that particular remote slot, shouldn't it? So please also consider changing this:

      net.minecraft.world.inventory.AbstractContainerMenu
      public void setItem(int slotId, int stateId, ItemStack item) {
          getSlot(slotId).set(item); // Line 593
          setRemoteSlot(slotId, item); // New line
          this.stateId = stateId; // Line 594
      }
      

      That is the setItem method from above, by the way.

            Unassigned Unassigned
            Rob23 Rob23
            Votes:
            3 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              CHK: