From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Sun, 1 May 2016 21:19:14 -0400 Subject: [PATCH] LootTable API & Replenishable Lootables Feature 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" diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java index 5baccb8d50c135ab20c38ffd0690f585514ce5af..eb04fdb172a50ec1f5b7fe78fa0e7655246abd60 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -269,4 +269,26 @@ public class PaperWorldConfig { this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax); log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax); } + + public boolean autoReplenishLootables; + public boolean restrictPlayerReloot; + public boolean changeLootTableSeedOnFill; + public int maxLootableRefills; + public int lootableRegenMin; + public int lootableRegenMax; + private void enhancedLootables() { + autoReplenishLootables = getBoolean("lootables.auto-replenish", false); + restrictPlayerReloot = getBoolean("lootables.restrict-player-reloot", true); + changeLootTableSeedOnFill = getBoolean("lootables.reset-seed-on-fill", true); + maxLootableRefills = getInt("lootables.max-refills", -1); + lootableRegenMin = PaperConfig.getSeconds(getString("lootables.refresh-min", "12h")); + lootableRegenMax = PaperConfig.getSeconds(getString("lootables.refresh-max", "2d")); + if (autoReplenishLootables) { + log("Lootables: Replenishing every " + + PaperConfig.timeSummary(lootableRegenMin) + " to " + + PaperConfig.timeSummary(lootableRegenMax) + + (restrictPlayerReloot ? " (restricting reloot)" : "") + ); + } + } } diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java new file mode 100644 index 0000000000000000000000000000000000000000..5dfc3c8008d64ad4ed71b4904c897f5005491349 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java @@ -0,0 +1,33 @@ +package com.destroystokyo.paper.loottable; + +import net.minecraft.core.BlockPosition; +import net.minecraft.world.level.World; +import net.minecraft.world.level.block.entity.TileEntityLootable; +import org.bukkit.Chunk; +import org.bukkit.block.Block; + +public interface PaperLootableBlockInventory extends LootableBlockInventory, PaperLootableInventory { + + TileEntityLootable getTileEntity(); + + @Override + default LootableInventory getAPILootableInventory() { + return this; + } + + @Override + default World getNMSWorld() { + return getTileEntity().getWorld(); + } + + default Block getBlock() { + final BlockPosition position = getTileEntity().getPosition(); + final Chunk bukkitChunk = getTileEntity().getWorld().getChunkAtWorldCoords(position).bukkitChunk; + return bukkitChunk.getBlock(position.getX(), position.getY(), position.getZ()); + } + + @Override + default PaperLootableInventoryData getLootableData() { + return getTileEntity().lootableData; + } +} diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java new file mode 100644 index 0000000000000000000000000000000000000000..019a06fa2b43cacd3bbd4d58aba71b3728f37581 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java @@ -0,0 +1,28 @@ +package com.destroystokyo.paper.loottable; + +import net.minecraft.world.level.World; +import org.bukkit.entity.Entity; + +public interface PaperLootableEntityInventory extends LootableEntityInventory, PaperLootableInventory { + + net.minecraft.world.entity.Entity getHandle(); + + @Override + default LootableInventory getAPILootableInventory() { + return this; + } + + default Entity getEntity() { + return getHandle().getBukkitEntity(); + } + + @Override + default World getNMSWorld() { + return getHandle().getWorld(); + } + + @Override + default PaperLootableInventoryData getLootableData() { + return getHandle().lootableData; + } +} diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java new file mode 100644 index 0000000000000000000000000000000000000000..59e8aea749bbba079e3304d9a5854280db2692e9 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java @@ -0,0 +1,71 @@ +package com.destroystokyo.paper.loottable; + +import net.minecraft.world.level.World; +import org.bukkit.loot.Lootable; + +import java.util.UUID; + +public interface PaperLootableInventory extends LootableInventory, Lootable { + + PaperLootableInventoryData getLootableData(); + LootableInventory getAPILootableInventory(); + + World getNMSWorld(); + + default org.bukkit.World getBukkitWorld() { + return getNMSWorld().getWorld(); + } + + @Override + default boolean isRefillEnabled() { + return getNMSWorld().paperConfig.autoReplenishLootables; + } + + @Override + default boolean hasBeenFilled() { + return getLastFilled() != -1; + } + + @Override + default boolean hasPlayerLooted(UUID player) { + return getLootableData().hasPlayerLooted(player); + } + + @Override + default Long getLastLooted(UUID player) { + return getLootableData().getLastLooted(player); + } + + @Override + default boolean setHasPlayerLooted(UUID player, boolean looted) { + final boolean hasLooted = hasPlayerLooted(player); + if (hasLooted != looted) { + getLootableData().setPlayerLootedState(player, looted); + } + return hasLooted; + } + + @Override + default boolean hasPendingRefill() { + long nextRefill = getLootableData().getNextRefill(); + return nextRefill != -1 && nextRefill > getLootableData().getLastFill(); + } + + @Override + default long getLastFilled() { + return getLootableData().getLastFill(); + } + + @Override + default long getNextRefill() { + return getLootableData().getNextRefill(); + } + + @Override + default long setNextRefill(long refillAt) { + if (refillAt < -1) { + refillAt = -1; + } + return getLootableData().setNextRefill(refillAt); + } +} diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java new file mode 100644 index 0000000000000000000000000000000000000000..904332454ede006f4ee33337d46b11674d78bef7 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java @@ -0,0 +1,181 @@ +package com.destroystokyo.paper.loottable; + +import com.destroystokyo.paper.PaperWorldConfig; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.world.entity.player.EntityHuman; +import org.bukkit.entity.Player; +import org.bukkit.loot.LootTable; + +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.UUID; + +public class PaperLootableInventoryData { + + private static final Random RANDOM = new Random(); + + private long lastFill = -1; + private long nextRefill = -1; + private int numRefills = 0; + private Map lootedPlayers; + private final PaperLootableInventory lootable; + + public PaperLootableInventoryData(PaperLootableInventory lootable) { + this.lootable = lootable; + } + + long getLastFill() { + return this.lastFill; + } + + long getNextRefill() { + return this.nextRefill; + } + + long setNextRefill(long nextRefill) { + long prev = this.nextRefill; + this.nextRefill = nextRefill; + return prev; + } + + public boolean shouldReplenish(@Nullable EntityHuman player) { + LootTable table = this.lootable.getLootTable(); + + // No Loot Table associated + if (table == null) { + return false; + } + + // ALWAYS process the first fill or if the feature is disabled + if (this.lastFill == -1 || !this.lootable.getNMSWorld().paperConfig.autoReplenishLootables) { + return true; + } + + // Only process refills when a player is set + if (player == null) { + return false; + } + + // Chest is not scheduled for refill + if (this.nextRefill == -1) { + return false; + } + + final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig; + + // Check if max refills has been hit + if (paperConfig.maxLootableRefills != -1 && this.numRefills >= paperConfig.maxLootableRefills) { + return false; + } + + // Refill has not been reached + if (this.nextRefill > System.currentTimeMillis()) { + return false; + } + + + final Player bukkitPlayer = (Player) player.getBukkitEntity(); + LootableInventoryReplenishEvent event = new LootableInventoryReplenishEvent(bukkitPlayer, lootable.getAPILootableInventory()); + if (paperConfig.restrictPlayerReloot && hasPlayerLooted(player.getUniqueID())) { + event.setCancelled(true); + } + return event.callEvent(); + } + public void processRefill(@Nullable EntityHuman player) { + this.lastFill = System.currentTimeMillis(); + final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig; + if (paperConfig.autoReplenishLootables) { + int min = paperConfig.lootableRegenMin; + int max = paperConfig.lootableRegenMax; + this.nextRefill = this.lastFill + (min + RANDOM.nextInt(max - min + 1)) * 1000L; + this.numRefills++; + if (paperConfig.changeLootTableSeedOnFill) { + this.lootable.setSeed(0); + } + if (player != null) { // This means that numRefills can be incremented without a player being in the lootedPlayers list - Seems to be EntityMinecartChest specific + this.setPlayerLootedState(player.getUniqueID(), true); + } + } else { + this.lootable.clearLootTable(); + } + } + + + public void loadNbt(NBTTagCompound base) { + if (!base.hasKeyOfType("Paper.LootableData", 10)) { // 10 = compound + return; + } + NBTTagCompound comp = base.getCompound("Paper.LootableData"); + if (comp.hasKey("lastFill")) { + this.lastFill = comp.getLong("lastFill"); + } + if (comp.hasKey("nextRefill")) { + this.nextRefill = comp.getLong("nextRefill"); + } + + if (comp.hasKey("numRefills")) { + this.numRefills = comp.getInt("numRefills"); + } + if (comp.hasKeyOfType("lootedPlayers", 9)) { // 9 = list + NBTTagList list = comp.getList("lootedPlayers", 10); // 10 = compound + final int size = list.size(); + if (size > 0) { + this.lootedPlayers = new HashMap<>(list.size()); + } + for (int i = 0; i < size; i++) { + final NBTTagCompound cmp = list.getCompound(i); + lootedPlayers.put(cmp.getUUID("UUID"), cmp.getLong("Time")); + } + } + } + public void saveNbt(NBTTagCompound base) { + NBTTagCompound comp = new NBTTagCompound(); + if (this.nextRefill != -1) { + comp.setLong("nextRefill", this.nextRefill); + } + if (this.lastFill != -1) { + comp.setLong("lastFill", this.lastFill); + } + if (this.numRefills != 0) { + comp.setInt("numRefills", this.numRefills); + } + if (this.lootedPlayers != null && !this.lootedPlayers.isEmpty()) { + NBTTagList list = new NBTTagList(); + for (Map.Entry entry : this.lootedPlayers.entrySet()) { + NBTTagCompound cmp = new NBTTagCompound(); + cmp.setUUID("UUID", entry.getKey()); + cmp.setLong("Time", entry.getValue()); + list.add(cmp); + } + comp.set("lootedPlayers", list); + } + + if (!comp.isEmpty()) { + base.set("Paper.LootableData", comp); + } + } + + void setPlayerLootedState(UUID player, boolean looted) { + if (looted && this.lootedPlayers == null) { + this.lootedPlayers = new HashMap<>(); + } + if (looted) { + if (!this.lootedPlayers.containsKey(player)) { + this.lootedPlayers.put(player, System.currentTimeMillis()); + } + } else if (this.lootedPlayers != null) { + this.lootedPlayers.remove(player); + } + } + + boolean hasPlayerLooted(UUID player) { + return this.lootedPlayers != null && this.lootedPlayers.containsKey(player); + } + + Long getLastLooted(UUID player) { + return lootedPlayers != null ? lootedPlayers.get(player) : null; + } +} diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java new file mode 100644 index 0000000000000000000000000000000000000000..c682bd7700d8103533026d46cfc63a7abde5a5f4 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java @@ -0,0 +1,62 @@ +package com.destroystokyo.paper.loottable; + +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.vehicle.EntityMinecartContainer; +import net.minecraft.world.level.World; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.util.CraftNamespacedKey; + +public class PaperMinecartLootableInventory implements PaperLootableEntityInventory { + + private EntityMinecartContainer entity; + + public PaperMinecartLootableInventory(EntityMinecartContainer entity) { + this.entity = entity; + } + + @Override + public org.bukkit.loot.LootTable getLootTable() { + return entity.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(entity.lootTable)) : null; + } + + @Override + public void setLootTable(org.bukkit.loot.LootTable table, long seed) { + setLootTable(table); + setSeed(seed); + } + + @Override + public void setSeed(long seed) { + entity.lootTableSeed = seed; + } + + @Override + public long getSeed() { + return entity.lootTableSeed; + } + + @Override + public void setLootTable(org.bukkit.loot.LootTable table) { + entity.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); + } + + @Override + public PaperLootableInventoryData getLootableData() { + return entity.lootableData; + } + + @Override + public Entity getHandle() { + return entity; + } + + @Override + public LootableInventory getAPILootableInventory() { + return (LootableInventory) entity.getBukkitEntity(); + } + + @Override + public World getNMSWorld() { + return entity.world; + } +} diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java new file mode 100644 index 0000000000000000000000000000000000000000..9dae34370d014a291f025f83b55e18bff4619a23 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java @@ -0,0 +1,65 @@ +package com.destroystokyo.paper.loottable; + +import net.minecraft.server.MCUtil; +import net.minecraft.world.level.World; +import net.minecraft.world.level.block.entity.TileEntityLootable; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.util.CraftNamespacedKey; + +public class PaperTileEntityLootableInventory implements PaperLootableBlockInventory { + private TileEntityLootable tileEntityLootable; + + public PaperTileEntityLootableInventory(TileEntityLootable tileEntityLootable) { + this.tileEntityLootable = tileEntityLootable; + } + + @Override + public org.bukkit.loot.LootTable getLootTable() { + return tileEntityLootable.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(tileEntityLootable.lootTable)) : null; + } + + @Override + public void setLootTable(org.bukkit.loot.LootTable table, long seed) { + setLootTable(table); + setSeed(seed); + } + + @Override + public void setLootTable(org.bukkit.loot.LootTable table) { + tileEntityLootable.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); + } + + @Override + public void setSeed(long seed) { + tileEntityLootable.lootTableSeed = seed; + } + + @Override + public long getSeed() { + return tileEntityLootable.lootTableSeed; + } + + @Override + public PaperLootableInventoryData getLootableData() { + return tileEntityLootable.lootableData; + } + + @Override + public TileEntityLootable getTileEntity() { + return tileEntityLootable; + } + + @Override + public LootableInventory getAPILootableInventory() { + World world = tileEntityLootable.getWorld(); + if (world == null) { + return null; + } + return (LootableInventory) getBukkitWorld().getBlockAt(MCUtil.toLocation(world, tileEntityLootable.getPosition())).getState(); + } + + @Override + public World getNMSWorld() { + return tileEntityLootable.getWorld(); + } +} diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java index 6cbb797cb0de4b26d8ddd7f0bf567f49bd36f9c0..2b1b46bda48c0b137fe914c47a387e6e72a1be40 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -158,6 +158,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, ne }; // Paper end + public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper private CraftEntity bukkitEntity; public CraftEntity getBukkitEntity() { diff --git a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java index c4b970c37b1792ac0022936f2df4740183621a0d..0166d11cb540a536390f486e1069d6119d8d23d6 100644 --- a/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java +++ b/src/main/java/net/minecraft/world/entity/vehicle/EntityMinecartContainer.java @@ -46,6 +46,7 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp public long lootTableSeed; // CraftBukkit start + { this.lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperMinecartLootableInventory(this)); } // Paper public List transaction = new java.util.ArrayList(); private int maxStack = MAX_STACK; @@ -203,12 +204,13 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp @Override protected void saveData(NBTTagCompound nbttagcompound) { super.saveData(nbttagcompound); + this.lootableData.saveNbt(nbttagcompound); // Paper if (this.lootTable != null) { nbttagcompound.setString("LootTable", this.lootTable.toString()); if (this.lootTableSeed != 0L) { nbttagcompound.setLong("LootTableSeed", this.lootTableSeed); } - } else { + } if (true) { // Paper - Always save the items, Table may stick around ContainerUtil.a(nbttagcompound, this.items); } @@ -217,11 +219,12 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp @Override protected void loadData(NBTTagCompound nbttagcompound) { super.loadData(nbttagcompound); + this.lootableData.loadNbt(nbttagcompound); // Paper this.items = NonNullList.a(this.getSize(), ItemStack.b); if (nbttagcompound.hasKeyOfType("LootTable", 8)) { this.lootTable = new MinecraftKey(nbttagcompound.getString("LootTable")); this.lootTableSeed = nbttagcompound.getLong("LootTableSeed"); - } else { + } if (true) { // Paper - always load the items, table may still remain ContainerUtil.b(nbttagcompound, this.items); } @@ -252,14 +255,15 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp } public void d(@Nullable EntityHuman entityhuman) { - if (this.lootTable != null && this.world.getMinecraftServer() != null) { + if (this.lootableData.shouldReplenish(entityhuman) && this.world.getMinecraftServer() != null) { // Paper LootTable loottable = this.world.getMinecraftServer().getLootTableRegistry().getLootTable(this.lootTable); if (entityhuman instanceof EntityPlayer) { CriterionTriggers.N.a((EntityPlayer) entityhuman, this.lootTable); } - this.lootTable = null; + //this.lootTable = null; // Paper + this.lootableData.processRefill(entityhuman); // Paper LootTableInfo.Builder loottableinfo_builder = (new LootTableInfo.Builder((WorldServer) this.world)).set(LootContextParameters.ORIGIN, this.getPositionVector()).a(this.lootTableSeed); if (entityhuman != null) { diff --git a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java index 62e6833a90d7adae3c7df33e3bc73b4288e0370b..1508e267a38555820e2d31f3075adca185fbd4b6 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java +++ b/src/main/java/net/minecraft/world/level/block/entity/TileEntityLootable.java @@ -27,6 +27,7 @@ public abstract class TileEntityLootable extends TileEntityContainer { @Nullable public MinecraftKey lootTable; public long lootTableSeed; + public final com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperTileEntityLootableInventory(this)); // Paper protected TileEntityLootable(TileEntityTypes tileentitytypes) { super(tileentitytypes); @@ -42,16 +43,19 @@ public abstract class TileEntityLootable extends TileEntityContainer { } protected boolean b(NBTTagCompound nbttagcompound) { + this.lootableData.loadNbt(nbttagcompound); // Paper if (nbttagcompound.hasKeyOfType("LootTable", 8)) { this.lootTable = new MinecraftKey(nbttagcompound.getString("LootTable")); + try { org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.lootTable); } catch (IllegalArgumentException ex) { this.lootTable = null; } // Paper - validate this.lootTableSeed = nbttagcompound.getLong("LootTableSeed"); - return true; + return false; // Paper - always load the items, table may still remain } else { return false; } } protected boolean c(NBTTagCompound nbttagcompound) { + this.lootableData.saveNbt(nbttagcompound); // Paper if (this.lootTable == null) { return false; } else { @@ -60,19 +64,20 @@ public abstract class TileEntityLootable extends TileEntityContainer { nbttagcompound.setLong("LootTableSeed", this.lootTableSeed); } - return true; + return false; // Paper - always save the items, table may still remain } } public void d(@Nullable EntityHuman entityhuman) { - if (this.lootTable != null && this.world.getMinecraftServer() != null) { + if (this.lootableData.shouldReplenish(entityhuman) && this.world.getMinecraftServer() != null) { // Paper LootTable loottable = this.world.getMinecraftServer().getLootTableRegistry().getLootTable(this.lootTable); if (entityhuman instanceof EntityPlayer) { CriterionTriggers.N.a((EntityPlayer) entityhuman, this.lootTable); } - this.lootTable = null; + //this.lootTable = null; // Paper + this.lootableData.processRefill(entityhuman); // Paper LootTableInfo.Builder loottableinfo_builder = (new LootTableInfo.Builder((WorldServer) this.world)).set(LootContextParameters.ORIGIN, Vec3D.a((BaseBlockPosition) this.position)).a(this.lootTableSeed); if (entityhuman != null) { diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java index 524f27830752f424493c3ae8d793b871f6495594..dcf3f9265b0b00a7bbb9ff428e10da3c198ba08a 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java @@ -64,7 +64,7 @@ public class CraftBlockEntityState extends CraftBlockState } // gets the wrapped TileEntity - protected T getTileEntity() { + public T getTileEntity() { // Paper - protected -> public return tileEntity; } diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java index 486fa8937d644f59a770db163482259525a7e465..54eb170fd533b0e91572601268fcbc167ed9bb5c 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java @@ -12,8 +12,9 @@ import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.inventory.CraftInventory; import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest; import org.bukkit.inventory.Inventory; +import com.destroystokyo.paper.loottable.PaperLootableBlockInventory; // Paper -public class CraftChest extends CraftLootable implements Chest { +public class CraftChest extends CraftLootable implements Chest, PaperLootableBlockInventory { // Paper public CraftChest(final Block block) { super(block, TileEntityChest.class); diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java index f0a7e61a26c4668a9aa823d641f29bdecd42dd1f..3512054ede5fd1dd7605444e827e30a0be47f935 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java @@ -10,7 +10,7 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey; import org.bukkit.loot.LootTable; import org.bukkit.loot.Lootable; -public abstract class CraftLootable extends CraftContainer implements Nameable, Lootable { +public abstract class CraftLootable extends CraftContainer implements Nameable, Lootable, com.destroystokyo.paper.loottable.PaperLootableBlockInventory { // Paper public CraftLootable(Block block, Class tileEntityClass) { super(block, tileEntityClass); @@ -54,7 +54,7 @@ public abstract class CraftLootable extends CraftC setLootTable(getLootTable(), seed); } - private void setLootTable(LootTable table, long seed) { + public void setLootTable(LootTable table, long seed) { // Paper - public MinecraftKey key = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); getSnapshot().setLootTable(key, seed); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java index cbd121c21adfaf098dadca33de16a2e68d83c19a..d9a2552782c9242fb84cc0c8309a614a44777509 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java @@ -8,7 +8,7 @@ import org.bukkit.entity.minecart.StorageMinecart; import org.bukkit.inventory.Inventory; @SuppressWarnings("deprecation") -public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart { +public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper private final CraftInventory inventory; public CraftMinecartChest(CraftServer server, EntityMinecartChest entity) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java index 5ffb8108f456c2f7f3ed1a25249baccb4cbf4add..bf8b5b25d1af0c5129261e10abf2866521b2c375 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java @@ -47,7 +47,7 @@ public abstract class CraftMinecartContainer extends CraftMinecart implements Lo return getHandle().lootTableSeed; } - private void setLootTable(LootTable table, long seed) { + public void setLootTable(LootTable table, long seed) { // Paper MinecraftKey newKey = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey()); getHandle().setLootTable(newKey, seed); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java index 17a42aec76f32a28b0c9885c60d1ed50c6727161..bfdcf01d2c6570493e86330d56500427dbb23146 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java @@ -7,7 +7,7 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.minecart.HopperMinecart; import org.bukkit.inventory.Inventory; -public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart { +public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart, com.destroystokyo.paper.loottable.PaperLootableEntityInventory { // Paper private final CraftInventory inventory; public CraftMinecartHopper(CraftServer server, EntityMinecartHopper entity) {