Paper icon indicating copy to clipboard operation
Paper copied to clipboard

lootgenerateevent.getloottable annotated as notnull but can be null sometimes

Open AnnotationVisitor opened this issue 2 months ago • 2 comments

Expected behavior

loot table never null

Observed/Actual behavior

java.lang.NullPointerException: Cannot invoke "org.bukkit.loot.LootTable.getKey()" because the return value of "org.bukkit.event.world.LootGenerateEvent.getLootTable()" is null at ListenEvents.jar/com.calummc.test.Listeners.onLootTableGenerate(Listeners.java:120) ~[ListenEvents.jar:?] at co.aikar.timings.TimedEventExecutor.execute(TimedEventExecutor.java:80) ~[paper-api-1.21.8-R0.1-SNAPSHOT.jar:?] at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:71) ~[paper-api-1.21.8-R0.1-SNAPSHOT.jar:?]

code line: @EventHandler(priority = EventPriority.HIGH) public void onLootTableGenerate(LootGenerateEvent event) { if (event.getLootTable().getKey().getKey().contains("testloot")) {

Steps/models to reproduce

idk

Plugin and Datapack List

N/A

Paper version

https://github.com/PaperMC/Paper/commit/29c8822d90899c89d2689338e81a98f690bcba12

Other

No response

AnnotationVisitor avatar Nov 01 '25 16:11 AnnotationVisitor

I can confirm, I faced this issue few months ago. Here's the steps to reproduce it:

  • Place a chest with an unknown loot table: /setblock ~ ~ ~ chest{LootTable:"unknownloottable"}
  • Register an event listener for LootGenerateEvent and print event.getLootTable()
  • Open the chest
  • The console will show null as a result, despite the LootGenerateEvent#getLootTable() method being annotated as @NotNull

This is because obviously the loot table does not exist, so the method can't return a LootTable object.

Additionally, since event.getLootTable().getKey() is the only way to get the key of the loot table involved in this event, this makes it impossible for plugins to get the unknownloottable key from my example. This is unfortunate, because even if the loot table does not exist on the server, that key is still present on the block, and could be interesting to know (at the very least to allow logging something like "Tried to generate loot for unknown loot table: unknownloottable").

So, my suggestion to fix this issue would be:

  1. Obviously annotate this method as @Nullable, because it could return null;
  2. Then, add another method LootGenerateEvent#getLootTableKey() returning the @NotNull Key of the loot table involved in this event, even if the real one does not exist.

To illustrate, my use case was to replace loots from some datapacks, and my initial intent was to react to the event, replace loots with items generated from my custom logic when the key matched some condition (namespace of the datapack, prefix...), then wipe the datapack's loot tables folder, just to make sure they'll never get generated "by mistake" if the plugin failed to overwrite it. However, I realized that this wasn't possible to get the loot table key anymore once I deleted the real loot tables...

indyteo avatar Nov 13 '25 09:11 indyteo

Okay the issue is the LootTable in the event its from extra value added to NMS LootTable this is created when the loot tables are validated (the loot tables register in the server) in this case a random loot table was not register then not has that extra data and the event can return null...

maybe can fix that when try to get the loottable and check that case for create the missing extra data...

Doc94 avatar Nov 13 '25 17:11 Doc94