PaperMC / PaperMC/Paper

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

Open
#11,245 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: accepted type: bug version: 1.21.8
Dominant language
Java
Stars
12.7k
Forks
3.5k
Avg merge
3d 13h
Merged PRs (30d)
11

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:

https://github.com/user-attachments/assets/e8c541ee-25a4-4a4b-ba79-af4f613645a3

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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the InventoryClickEvent listener and the player.openInventory(target.getInventory()) reproduction from the linked PaperBugExample repository. Compare the reported slot and item across the listed Paper versions, especially the change between 1.13.2 and 1.14.4. Done means clicks in the bottom inventory report the correct item and slot when another player's inventory is open.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.