Expected behavior
PlayerDeathEvent custom drops are not mutated in any way by the server after the event is handled.
Observed/Actual behavior
PlayerDeathEvent custom drops are mutated into AIR by the server after the event is handled.
Steps/models to reproduce
Given the following (somewhat contrived) example code:
package org.example.plugin;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
public class ExamplePlugin extends JavaPlugin implements Listener {
@Override
public void onEnable() {
getServer().getPluginManager().registerEvents(this, this);
}
@EventHandler
public void onPlayerDeath(PlayerDeathEvent e) {
final ItemStack itemStack = new ItemStack(Material.DIAMOND);
// Any custom drops added are affected by this issue
e.getDrops().add(itemStack);
// This one prints the diamond, it's fine.
getLogger().info(">>> Item stack before PlayerDeathEvent: " + itemStack);
getServer().getScheduler().runTask(this, () -> {
// This one prints AIR, where did the diamond go?
// If you attach a debugger you can see that the underlying NMS item is still
// a diamond, but the item stack count is set to 0, which is why the item is treated as AIR.
getLogger().info(">>> Item stack after PlayerDeathEvent: " + itemStack);
});
}
}
You should be able to observe the following output when a player dies (e.g. using /kill):
[ExamplePlugin] >>> Item stack before PlayerDeathEvent: ItemStack{DIAMOND x 1}
[ExamplePlugin] >>> Item stack after PlayerDeathEvent: ItemStack{AIR x 0}
As you can see, the item stack added as a custom drop was mutated into AIR by the server. Note that this issue only affects custom drops added, not any of the original drops that the player had in their inventory.
Plugin and Datapack List
[03:14:44 INFO]: Server Plugins (1):
[03:14:44 INFO]: Bukkit Plugins:
[03:14:44 INFO]: - ExamplePlugin
[03:15:38 INFO]: There are 3 data pack(s) enabled: [vanilla (built-in)], [file/bukkit (world)], [paper (built-in)]
[03:15:38 INFO]: There are no more data packs available
Paper version
[03:16:13 INFO]: Checking version, please wait...
[03:16:13 INFO]: This server is running Paper version 1.21.1-128-master@d348cb8 (2024-10-21T16:23:24Z) (Implementing API version 1.21.1-R0.1-SNAPSHOT)
You are running the latest version
Other
After some testing, I can conclude that this seems to be a regression introduced in build 79 for Minecraft 1.21.1, i.e. commit 0a53f1d. On earlier builds, the drops are not mutated into air and so both of the log statements in the example code print a diamond, as expected.
I didn't debug far enough to tell what code path is setting the item stack count to 0, but to me it seems like the regression introduced in build 79 is that the custom drop item stacks are no longer copied, so if the server mutates them then that will now affect the API user. I'm not entirely sure if the API user should guard against this by cloning the item stack or if this is a bug that should be fixed in Paper, but I'm leaning toward the latter. In which case, please see my PR #11521 for a possible patch to fix this regression.
Let me know if this seems correct or if I have perhaps misunderstood something.
Expected behavior
PlayerDeathEventcustom drops are not mutated in any way by the server after the event is handled.Observed/Actual behavior
PlayerDeathEventcustom drops are mutated into AIR by the server after the event is handled.Steps/models to reproduce
Given the following (somewhat contrived) example code:
You should be able to observe the following output when a player dies (e.g. using
/kill):As you can see, the item stack added as a custom drop was mutated into AIR by the server. Note that this issue only affects custom drops added, not any of the original drops that the player had in their inventory.
Plugin and Datapack List
Paper version
Other
After some testing, I can conclude that this seems to be a regression introduced in build 79 for Minecraft 1.21.1, i.e. commit 0a53f1d. On earlier builds, the drops are not mutated into air and so both of the log statements in the example code print a diamond, as expected.
I didn't debug far enough to tell what code path is setting the item stack count to 0, but to me it seems like the regression introduced in build 79 is that the custom drop item stacks are no longer copied, so if the server mutates them then that will now affect the API user. I'm not entirely sure if the API user should guard against this by cloning the item stack or if this is a bug that should be fixed in Paper, but I'm leaning toward the latter. In which case, please see my PR #11521 for a possible patch to fix this regression.
Let me know if this seems correct or if I have perhaps misunderstood something.