LootTable API and replenishable lootables

Provides an API to control the loot table for an object.
Also provides a feature that any Lootable Inventory (Chests in Structures)
can automatically replenish after a given time.

This feature is good for long term worlds so that newer players
do not suffer with "Every chest has been looted"

== AT ==
public org.bukkit.craftbukkit.block.CraftBlockEntityState getTileEntity()Lnet/minecraft/world/level/block/entity/BlockEntity;
public org.bukkit.craftbukkit.block.CraftLootable setLootTable(Lorg/bukkit/loot/LootTable;J)V
public org.bukkit.craftbukkit.entity.CraftMinecartContainer setLootTable(Lorg/bukkit/loot/LootTable;J)V
This commit is contained in:
Aikar
2016-05-01 21:19:14 -04:00
parent b8d05bbc27
commit 07c767b6f4
19 changed files with 718 additions and 74 deletions

View File

@@ -0,0 +1,41 @@
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -137,7 +137,7 @@
itemEntity.setDefaultPickUpDelay();
world.addFreshEntity(itemEntity);
} else {
- shulkerBoxBlockEntity.unpackLootTable(player);
+ shulkerBoxBlockEntity.unpackLootTable(player, true); // Paper - force clear loot table so replenish data isn't persisted in the stack
}
}
@@ -147,7 +147,15 @@
@Override
protected List<ItemStack> getDrops(BlockState state, LootParams.Builder builder) {
BlockEntity blockEntity = builder.getOptionalParameter(LootContextParams.BLOCK_ENTITY);
+ Runnable reAdd = null; // Paper
if (blockEntity instanceof ShulkerBoxBlockEntity shulkerBoxBlockEntity) {
+ // Paper start - clear loot table if it was already used
+ if (shulkerBoxBlockEntity.lootableData().getLastFill() != -1 || !builder.getLevel().paperConfig().lootables.retainUnlootedShulkerBoxLootTableOnNonPlayerBreak) {
+ net.minecraft.resources.ResourceKey<net.minecraft.world.level.storage.loot.LootTable> lootTableResourceKey = shulkerBoxBlockEntity.getLootTable();
+ reAdd = () -> shulkerBoxBlockEntity.setLootTable(lootTableResourceKey);
+ shulkerBoxBlockEntity.setLootTable(null);
+ }
+ // Paper end
builder = builder.withDynamicDrop(CONTENTS, lootConsumer -> {
for (int i = 0; i < shulkerBoxBlockEntity.getContainerSize(); i++) {
lootConsumer.accept(shulkerBoxBlockEntity.getItem(i));
@@ -155,7 +163,13 @@
});
}
+ // Paper start - re-set loot table if it was cleared
+ try {
return super.getDrops(state, builder);
+ } finally {
+ if (reAdd != null) reAdd.run();
+ }
+ // Paper end - re-set loot table if it was cleared
}
@Override

View File

@@ -0,0 +1,16 @@
--- a/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
@@ -115,4 +115,13 @@
nbt.remove("LootTable");
nbt.remove("LootTableSeed");
}
+
+ // Paper start - LootTable API
+ final com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(); // Paper
+
+ @Override
+ public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData() {
+ return this.lootableData;
+ }
+ // Paper end - LootTable API
}