PaperMC / PaperMC/Paper

PlayerInventorySlotChangeEvent#getSlot() returns misleading slot when armor changes while another inventory is open`

Open
#13,991 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: needs triage version: 26.1.2
Dominant language
Java
Stars
12.7k
Forks
3.5k
Avg merge
3d 13h
Merged PRs (30d)
11

Description

Expected behavior

PlayerInventorySlotChangeEvent#getSlot() and PlayerInventorySlotChangeEvent#getRawSlot() should reliably identify the changed slot in the player's own inventory, especially for armor/offhand slots.

Observed/Actual behavior

When a player has another inventory view open, for example a chest, and an armor slot changes due to external causes, such as a zombie attacking the player and damaging armor durability, PlayerInventorySlotChangeEvent is fired, but the slot values appear incorrect or misleading.

In this case:

  • event.getRawSlot() does not behave as expected for the currently changed player inventory slot.
  • event.getSlot() appears to be converted using the currently open InventoryView.
  • Because the player is viewing a chest, event.getSlot() may map to a slot in the chest view instead of representing the actual armor slot that changed.

This makes it difficult or impossible for plugins to safely detect armor slot changes using this event while the player has another container open.

Steps/models to reproduce
  1. Create a plugin that listens to PlayerInventorySlotChangeEvent.
  2. Log the following values:
    • event.getRawSlot()
    • event.getSlot()
    • event.getOldItemStack()
    • event.getNewItemStack()
    • player.getOpenInventory().getType()
  3. Equip armor on the player.
  4. Open a chest.
  5. Let a zombie attack the player so that the armor durability changes.
  6. Observe the logged slot values.
Plugin and Datapack List

None except for a test plugin, source code:
Example listener:

@EventHandler
public void onSlotChange(PlayerInventorySlotChangeEvent event) {
    Player player = event.getPlayer();

    player.sendMessage("Open view: " + player.getOpenInventory().getType());
    player.sendMessage("Raw slot: " + event.getRawSlot());
    player.sendMessage("Slot: " + event.getSlot());
    player.sendMessage("Old item: " + event.getOldItemStack());
    player.sendMessage("New item: " + event.getNewItemStack());
}
Paper version

This server is running Paper version 26.1.2-69-main@76d2ac7 (2026-06-03T17:32:02Z) (Implementing API version 26.1.2.build.69-stable)

Other

If this is an unsolvable problem or work as excepted, it should at least be ensured that the PlayerInventorySlot ChangeEvent is not triggered in this situation, otherwise the plugin will listen for incorrect slot values in this situation, causing various chain problems.

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 PlayerInventorySlotChangeEvent and reproduce the case using the listener shown in the issue: open a chest, equip armor, and trigger durability damage. Compare getRawSlot() and getSlot() with the player's inventory and open view; done means armor and offhand changes identify the correct player-inventory slots, or the event is not fired when those values cannot be represented reliably.

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
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.