Skip to content

Clicking bottom inventory items while another player's inventory is opened up at the top fires InventoryClickEvent with incorrect items and slots #11245

@ghost

Description

Expected behavior

InventoryClickEvent should not report incorrect slots and/or items on the bottom inventory when another player's inventory is opened up in the top.

Observed/Actual behavior

When having another player's inventory opened up, attempting to click an item from the bottom inventory (our own inventory) will fire an InventoryClickEvent with an incorrect slot/item:

javaw_sRTWvdj4ta.mp4

I have tested the following versions, all of which have the issue:

  • Paper 1.21.1 build 10
  • Paper 1.20.6 build 148
  • Paper 1.18.2 build 388
  • Paper 1.14.4 build 245

The following versions do NOT have the issue:

  • Paper 1.13.2 build 657
  • Paper 1.12.2 build 1620

Steps/models to reproduce

Example repository: https://github.com/xwmi/paper-bug-poc (check the legacy branch for a version of the plugin that works on older Paper versions using a Diamond instead of netherite hoes)

  1. Create an InventoryClickEvent listener that will cancel movement for a specific item (e.g. a netherite hoe):
    @EventHandler
    public void onInventoryClickEvent(InventoryClickEvent event) {
        ItemStack currentItem = event.getCurrentItem();
        int slot = event.getSlot();
        int rawSlot = event.getRawSlot();

        // Broadcast some debug information. We could also just print it to the console.
        String itemType = currentItem != null ? currentItem.getType().name() : "none";
        Bukkit.broadcast(Component.text("The clicked item type is " + itemType));
        Bukkit.broadcast(Component.text("The clicked slot is " + slot));
        Bukkit.broadcast(Component.text("The raw slot is " + rawSlot));

        // Let's not cancel the event if it isn't a Netherite Hoe
        if (currentItem == null || currentItem.getType() != Material.NETHERITE_HOE) {
            return;
        }

        @NotNull HumanEntity entity = event.getWhoClicked();

        // This should, in theory, prevent a Netherite Hoe from being moved
        // around the inventory when the top inventory is from another player
        if (entity.getOpenInventory().getTopInventory().getType() == InventoryType.PLAYER) {
            event.setCancelled(true);
            Bukkit.broadcast(Component.text("Cancelled Netherite Hoe movement " +
                    "because the top inventory is from a player"));
        } else {
            Bukkit.broadcast(Component.text("Not cancelling Netherite Hoe movement " +
                    "because the top inventory is not from a player"));
        }
    }
  1. Create a command that will open another player's inventory like this (EssentialsX has an /invsee command that will also work for this):
Player target = ...
player.openInventory(target.getInventory());
  1. Attempt to click the Netherite Hoe or some other slots around it. The event will report as if a completely unrelated slot was being clicked:

image

Plugin and Datapack List

> pl
[21:22:48 INFO]: Server Plugins (1):
[21:22:48 INFO]: Paper Plugins:
[21:22:48 INFO]:  - PaperBugExample
> datapack list
[21:22:51 INFO]: There are 3 data pack(s) enabled: [vanilla (built-in)], [file/bukkit (world)], [paper (built-in)]
[21:22:51 INFO]: There are no more data packs available

Paper version

> ver
[21:23:12 INFO]: This server is running Paper version 1.21.1-10-master@098bd39 (2024-08-11T22:37:37Z) (Implementing API version 1.21.1-R0.1-SNAPSHOT)
You are running the latest version

Other

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: acceptedDisputed bug is accepted as valid or Feature accepted as desired to be added.type: bugSomething doesn't work as it was intended to.version: 1.21.8Game version 1.21.8

    Type

    No fields configured for Bug.

    Projects

    Status

    ✅ Accepted

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions