mirror of
https://github.com/PaperMC/Paper.git
synced 2025-01-19 07:33:11 +01:00
974b0afca9
CraftBukkit removed their implementation that caused this issue, switching to Mojang's implementation which doesn't appear to share it. I already removed the important bit in the last upstream merge, this is just unused and unnecessary now. So we remove it.
786 lines
29 KiB
Diff
786 lines
29 KiB
Diff
From bfc069f2e9f925c0f10d95b9cdbdd33ea8a3f8f7 Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
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 5cc55b794..fbe769eb3 100644
|
|
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
@@ -305,4 +305,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/CraftLootable.java b/src/main/java/com/destroystokyo/paper/loottable/CraftLootable.java
|
|
new file mode 100644
|
|
index 000000000..36c36d158
|
|
--- /dev/null
|
|
+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootable.java
|
|
@@ -0,0 +1,12 @@
|
|
+package com.destroystokyo.paper.loottable;
|
|
+
|
|
+import net.minecraft.server.World;
|
|
+
|
|
+interface CraftLootable extends Lootable {
|
|
+
|
|
+ World getNMSWorld();
|
|
+
|
|
+ default org.bukkit.World getBukkitWorld() {
|
|
+ return getNMSWorld().getWorld();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/com/destroystokyo/paper/loottable/CraftLootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableBlockInventory.java
|
|
new file mode 100644
|
|
index 000000000..20d236c45
|
|
--- /dev/null
|
|
+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableBlockInventory.java
|
|
@@ -0,0 +1,33 @@
|
|
+package com.destroystokyo.paper.loottable;
|
|
+
|
|
+import net.minecraft.server.BlockPosition;
|
|
+import net.minecraft.server.TileEntityLootable;
|
|
+import net.minecraft.server.World;
|
|
+import org.bukkit.Chunk;
|
|
+import org.bukkit.block.Block;
|
|
+
|
|
+public interface CraftLootableBlockInventory extends LootableBlockInventory, CraftLootableInventory {
|
|
+
|
|
+ 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 CraftLootableInventoryData getLootableData() {
|
|
+ return getTileEntity().getLootableData();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/com/destroystokyo/paper/loottable/CraftLootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableEntityInventory.java
|
|
new file mode 100644
|
|
index 000000000..1150dee01
|
|
--- /dev/null
|
|
+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableEntityInventory.java
|
|
@@ -0,0 +1,31 @@
|
|
+package com.destroystokyo.paper.loottable;
|
|
+
|
|
+import net.minecraft.server.World;
|
|
+import org.bukkit.entity.Entity;
|
|
+
|
|
+public interface CraftLootableEntityInventory extends LootableEntityInventory, CraftLootableInventory {
|
|
+
|
|
+ net.minecraft.server.Entity getHandle();
|
|
+
|
|
+ @Override
|
|
+ default LootableInventory getAPILootableInventory() {
|
|
+ return this;
|
|
+ }
|
|
+
|
|
+ default Entity getEntity() {
|
|
+ return getHandle().getBukkitEntity();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ default World getNMSWorld() {
|
|
+ return getHandle().getWorld();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ default CraftLootableInventoryData getLootableData() {
|
|
+ if (getHandle() instanceof CraftLootableInventory) {
|
|
+ return ((CraftLootableInventory) getHandle()).getLootableData();
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventory.java
|
|
new file mode 100644
|
|
index 000000000..668097620
|
|
--- /dev/null
|
|
+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventory.java
|
|
@@ -0,0 +1,88 @@
|
|
+package com.destroystokyo.paper.loottable;
|
|
+
|
|
+import org.apache.commons.lang.Validate;
|
|
+
|
|
+import java.util.UUID;
|
|
+
|
|
+public interface CraftLootableInventory extends CraftLootable, LootableInventory {
|
|
+
|
|
+ CraftLootableInventoryData getLootableData();
|
|
+ LootableInventory getAPILootableInventory();
|
|
+
|
|
+ @Override
|
|
+ default boolean isRefillEnabled() {
|
|
+ return getNMSWorld().paperConfig.autoReplenishLootables;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ default boolean hasBeenFilled() {
|
|
+ return getLastFilled() != -1;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ default String getLootTableName() {
|
|
+ return getLootableData().getLootable().getLootTableName();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ default String setLootTable(String name, long seed) {
|
|
+ Validate.notNull(name);
|
|
+
|
|
+ String prevLootTable = getLootTableName();
|
|
+ getLootableData().getLootable().setLootTable(name, seed);
|
|
+ return prevLootTable;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ default long getLootTableSeed() {
|
|
+ return getLootableData().getLootable().getLootTableSeed();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ default void clearLootTable() {
|
|
+ getLootableData().getLootable().clearLootTable();
|
|
+ }
|
|
+
|
|
+ @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/CraftLootableInventoryData.java b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventoryData.java
|
|
new file mode 100644
|
|
index 000000000..01c2713d3
|
|
--- /dev/null
|
|
+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventoryData.java
|
|
@@ -0,0 +1,182 @@
|
|
+package com.destroystokyo.paper.loottable;
|
|
+
|
|
+import com.destroystokyo.paper.PaperWorldConfig;
|
|
+import net.minecraft.server.*;
|
|
+import org.bukkit.entity.Player;
|
|
+
|
|
+import javax.annotation.Nullable;
|
|
+import java.util.HashMap;
|
|
+import java.util.Map;
|
|
+import java.util.Random;
|
|
+import java.util.UUID;
|
|
+
|
|
+public class CraftLootableInventoryData {
|
|
+
|
|
+ private static final Random RANDOM = new Random();
|
|
+
|
|
+ private long lastFill = -1;
|
|
+ private long nextRefill = -1;
|
|
+ private int numRefills = 0;
|
|
+ private Map<UUID, Long> lootedPlayers;
|
|
+ private final CraftLootableInventory lootable;
|
|
+
|
|
+ public CraftLootableInventoryData(CraftLootableInventory 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;
|
|
+ }
|
|
+
|
|
+ CraftLootableInventory getLootable() {
|
|
+ return lootable;
|
|
+ }
|
|
+
|
|
+ public boolean shouldReplenish(@Nullable EntityHuman player) {
|
|
+ String tableName = this.lootable.getLootTableName();
|
|
+
|
|
+ // No Loot Table associated
|
|
+ if (tableName == null) {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // ALWAYS process the first fill
|
|
+ if (this.lastFill == -1) {
|
|
+ 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 * 1000;
|
|
+ int max = paperConfig.lootableRegenMax * 1000;
|
|
+ this.nextRefill = this.lastFill + min + RANDOM.nextInt(max - min + 1);
|
|
+ this.numRefills++;
|
|
+ if (paperConfig.changeLootTableSeedOnFill) {
|
|
+ this.lootable.setLootTableSeed(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.get(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<UUID, Long> 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/net/minecraft/server/EntityMinecartContainer.java b/src/main/java/net/minecraft/server/EntityMinecartContainer.java
|
|
index a79919696..965aa5c23 100644
|
|
--- a/src/main/java/net/minecraft/server/EntityMinecartContainer.java
|
|
+++ b/src/main/java/net/minecraft/server/EntityMinecartContainer.java
|
|
@@ -6,17 +6,21 @@ import javax.annotation.Nullable;
|
|
// CraftBukkit start
|
|
import java.util.List;
|
|
import org.bukkit.Location;
|
|
+
|
|
+import com.destroystokyo.paper.loottable.CraftLootableInventoryData; // Paper
|
|
+import com.destroystokyo.paper.loottable.CraftLootableInventory; // Paper
|
|
+import com.destroystokyo.paper.loottable.LootableInventory; // Paper
|
|
import org.bukkit.craftbukkit.entity.CraftHumanEntity;
|
|
import org.bukkit.entity.HumanEntity;
|
|
import org.bukkit.inventory.InventoryHolder;
|
|
// CraftBukkit end
|
|
|
|
-public abstract class EntityMinecartContainer extends EntityMinecartAbstract implements ITileInventory, ILootable {
|
|
+public abstract class EntityMinecartContainer extends EntityMinecartAbstract implements ITileInventory, ILootable, CraftLootableInventory { // Paper
|
|
|
|
private NonNullList<ItemStack> items;
|
|
private boolean b;
|
|
private MinecraftKey c;
|
|
- private long d;
|
|
+ private long d;public long getLootTableSeed() { return d; } // Paper - OBFHELPER
|
|
|
|
// CraftBukkit start
|
|
public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
|
|
@@ -164,12 +168,13 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp
|
|
|
|
protected void b(NBTTagCompound nbttagcompound) {
|
|
super.b(nbttagcompound);
|
|
+ lootableData.saveNbt(nbttagcompound); // Paper
|
|
if (this.c != null) {
|
|
nbttagcompound.setString("LootTable", this.c.toString());
|
|
if (this.d != 0L) {
|
|
nbttagcompound.setLong("LootTableSeed", this.d);
|
|
}
|
|
- } else {
|
|
+ } if (true) { // Paper - Always save the items, Table may stick around
|
|
ContainerUtil.a(nbttagcompound, this.items);
|
|
}
|
|
|
|
@@ -181,7 +186,7 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp
|
|
if (nbttagcompound.hasKeyOfType("LootTable", 8)) {
|
|
this.c = new MinecraftKey(nbttagcompound.getString("LootTable"));
|
|
this.d = nbttagcompound.getLong("LootTableSeed");
|
|
- } else {
|
|
+ } if (true) { // Paper - always load the items, table may still remain
|
|
ContainerUtil.b(nbttagcompound, this.items);
|
|
}
|
|
|
|
@@ -230,10 +235,10 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp
|
|
}
|
|
|
|
public void f(@Nullable EntityHuman entityhuman) {
|
|
- if (this.c != null) {
|
|
+ if (lootableData.shouldReplenish(entityhuman)) { // Paper
|
|
LootTable loottable = this.world.ak().a(this.c);
|
|
|
|
- this.c = null;
|
|
+ lootableData.processRefill(entityhuman); // Paper
|
|
Random random;
|
|
|
|
if (this.d == 0L) {
|
|
@@ -258,12 +263,52 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp
|
|
this.items.clear();
|
|
}
|
|
|
|
+ public void setLootTable(MinecraftKey key, long seed) { a(key, seed);} // Paper - OBFHELPER
|
|
public void a(MinecraftKey minecraftkey, long i) {
|
|
this.c = minecraftkey;
|
|
this.d = i;
|
|
}
|
|
|
|
+
|
|
+ public MinecraftKey getLootTableKey() { return b(); } // Paper - OBFHELPER
|
|
public MinecraftKey b() {
|
|
return this.c;
|
|
}
|
|
+
|
|
+ // Paper start
|
|
+ private final CraftLootableInventoryData lootableData = new CraftLootableInventoryData(this);
|
|
+
|
|
+ @Override
|
|
+ public CraftLootableInventoryData getLootableData() {
|
|
+ return lootableData;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public LootableInventory getAPILootableInventory() {
|
|
+ return (LootableInventory) this.getBukkitEntity();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public World getNMSWorld() {
|
|
+ return this.world;
|
|
+ }
|
|
+
|
|
+ public String getLootTableName() {
|
|
+ final MinecraftKey key = getLootTableKey();
|
|
+ return key != null ? key.toString() : null;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String setLootTable(String name, long seed) {
|
|
+ String prev = getLootTableName();
|
|
+ setLootTable(new MinecraftKey(name), seed);
|
|
+ return prev;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void clearLootTable() {
|
|
+ //noinspection RedundantCast
|
|
+ this.c = (MinecraftKey) null;
|
|
+ }
|
|
+ // Paper end
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/TileEntityLootable.java b/src/main/java/net/minecraft/server/TileEntityLootable.java
|
|
index 5632f2e78..01d0d8071 100644
|
|
--- a/src/main/java/net/minecraft/server/TileEntityLootable.java
|
|
+++ b/src/main/java/net/minecraft/server/TileEntityLootable.java
|
|
@@ -1,44 +1,50 @@
|
|
package net.minecraft.server;
|
|
|
|
+import com.destroystokyo.paper.loottable.CraftLootableInventoryData; // Paper
|
|
+import com.destroystokyo.paper.loottable.CraftLootableInventory; // Paper
|
|
+import com.destroystokyo.paper.loottable.LootableInventory; // Paper
|
|
+
|
|
import java.util.Random;
|
|
import javax.annotation.Nullable;
|
|
|
|
-public abstract class TileEntityLootable extends TileEntityContainer implements ILootable {
|
|
+public abstract class TileEntityLootable extends TileEntityContainer implements ILootable, CraftLootableInventory { // Paper
|
|
|
|
protected MinecraftKey m;
|
|
- protected long n;
|
|
+ protected long n; public long getLootTableSeed() { return n; } // Paper - OBFHELPER
|
|
protected String o;
|
|
|
|
public TileEntityLootable() {}
|
|
|
|
protected boolean c(NBTTagCompound nbttagcompound) {
|
|
+ lootableData.loadNbt(nbttagcompound); // Paper
|
|
if (nbttagcompound.hasKeyOfType("LootTable", 8)) {
|
|
this.m = new MinecraftKey(nbttagcompound.getString("LootTable"));
|
|
this.n = nbttagcompound.getLong("LootTableSeed");
|
|
- return true;
|
|
+ return false; // Paper - always load the items, table may still remain
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
protected boolean d(NBTTagCompound nbttagcompound) {
|
|
+ lootableData.saveNbt(nbttagcompound); // Paper
|
|
if (this.m != null) {
|
|
nbttagcompound.setString("LootTable", this.m.toString());
|
|
if (this.n != 0L) {
|
|
nbttagcompound.setLong("LootTableSeed", this.n);
|
|
}
|
|
|
|
- return true;
|
|
+ return false; // Paper - always save the items, table may still remain
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public void d(@Nullable EntityHuman entityhuman) {
|
|
- if (this.m != null) {
|
|
+ if (lootableData.shouldReplenish(entityhuman)) { // Paper
|
|
LootTable loottable = this.world.ak().a(this.m);
|
|
|
|
- this.m = null;
|
|
+ lootableData.processRefill(entityhuman); // Paper
|
|
Random random;
|
|
|
|
if (this.n == 0L) {
|
|
@@ -58,10 +64,12 @@ public abstract class TileEntityLootable extends TileEntityContainer implements
|
|
|
|
}
|
|
|
|
+ public MinecraftKey getLootTableKey() { return b(); } // Paper - OBFHELPER
|
|
public MinecraftKey b() {
|
|
return this.m;
|
|
}
|
|
|
|
+ public void setLootTable(MinecraftKey key, long seed) { a(key, seed);} // Paper - OBFHELPER
|
|
public void a(MinecraftKey minecraftkey, long i) {
|
|
this.m = minecraftkey;
|
|
this.n = i;
|
|
@@ -134,4 +142,42 @@ public abstract class TileEntityLootable extends TileEntityContainer implements
|
|
}
|
|
|
|
protected abstract NonNullList<ItemStack> q();
|
|
+
|
|
+ // Paper start - LootTable API
|
|
+ private final CraftLootableInventoryData lootableData = new CraftLootableInventoryData(this);
|
|
+
|
|
+ @Override
|
|
+ public CraftLootableInventoryData getLootableData() {
|
|
+ return lootableData;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public LootableInventory getAPILootableInventory() {
|
|
+ return (LootableInventory) getBukkitWorld().getBlockAt(MCUtil.toLocation(world, getPosition())).getState();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public World getNMSWorld() {
|
|
+ return world;
|
|
+ }
|
|
+
|
|
+ public String getLootTableName() {
|
|
+ final MinecraftKey key = getLootTableKey();
|
|
+ return key != null ? key.toString() : null;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String setLootTable(String name, long seed) {
|
|
+ String prev = getLootTableName();
|
|
+ setLootTable(new MinecraftKey(name), seed);
|
|
+ return prev;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void clearLootTable() {
|
|
+ //noinspection RedundantCast
|
|
+ this.m = (MinecraftKey) null;
|
|
+ }
|
|
+ // Paper end
|
|
+
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
|
|
index 3de7e14d8..6cab545e5 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
|
|
@@ -1,5 +1,6 @@
|
|
package org.bukkit.craftbukkit.block;
|
|
|
|
+import com.destroystokyo.paper.loottable.CraftLootableBlockInventory; // Paper
|
|
import net.minecraft.server.BlockPosition;
|
|
import net.minecraft.server.TileEntityChest;
|
|
|
|
@@ -11,7 +12,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventory;
|
|
import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest;
|
|
import org.bukkit.inventory.Inventory;
|
|
|
|
-public class CraftChest extends CraftLootable implements Chest {
|
|
+public class CraftChest extends CraftLootable implements Chest, CraftLootableBlockInventory { // Paper
|
|
private final CraftWorld world;
|
|
private final TileEntityChest chest;
|
|
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java b/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java
|
|
index cc0d28f21..1b28e8ba2 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java
|
|
@@ -1,5 +1,6 @@
|
|
package org.bukkit.craftbukkit.block;
|
|
|
|
+import com.destroystokyo.paper.loottable.CraftLootableBlockInventory; // Paper
|
|
import net.minecraft.server.BlockDispenser;
|
|
import net.minecraft.server.BlockPosition;
|
|
import net.minecraft.server.Blocks;
|
|
@@ -14,7 +15,7 @@ import org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource;
|
|
import org.bukkit.inventory.Inventory;
|
|
import org.bukkit.projectiles.BlockProjectileSource;
|
|
|
|
-public class CraftDispenser extends CraftLootable implements Dispenser {
|
|
+public class CraftDispenser extends CraftLootable implements Dispenser, CraftLootableBlockInventory { // Paper
|
|
private final CraftWorld world;
|
|
private final TileEntityDispenser dispenser;
|
|
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java b/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java
|
|
index b7a04bd84..5d4a5519d 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java
|
|
@@ -1,5 +1,6 @@
|
|
package org.bukkit.craftbukkit.block;
|
|
|
|
+import com.destroystokyo.paper.loottable.CraftLootableBlockInventory; // Paper
|
|
import net.minecraft.server.TileEntityHopper;
|
|
import org.bukkit.Material;
|
|
import org.bukkit.block.Block;
|
|
@@ -8,7 +9,7 @@ import org.bukkit.craftbukkit.CraftWorld;
|
|
import org.bukkit.craftbukkit.inventory.CraftInventory;
|
|
import org.bukkit.inventory.Inventory;
|
|
|
|
-public class CraftHopper extends CraftLootable implements Hopper {
|
|
+public class CraftHopper extends CraftLootable implements Hopper, CraftLootableBlockInventory { // Paper
|
|
private final TileEntityHopper hopper;
|
|
|
|
public CraftHopper(final Block block) {
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java b/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java
|
|
index 8a7ce92bf..02f56bc0d 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java
|
|
@@ -1,5 +1,6 @@
|
|
package org.bukkit.craftbukkit.block;
|
|
|
|
+import com.destroystokyo.paper.loottable.CraftLootableBlockInventory;
|
|
import net.minecraft.server.BlockShulkerBox;
|
|
import net.minecraft.server.TileEntity;
|
|
import net.minecraft.server.TileEntityShulkerBox;
|
|
@@ -11,7 +12,7 @@ import org.bukkit.craftbukkit.CraftWorld;
|
|
import org.bukkit.craftbukkit.inventory.CraftInventory;
|
|
import org.bukkit.inventory.Inventory;
|
|
|
|
-public class CraftShulkerBox extends CraftLootable implements ShulkerBox {
|
|
+public class CraftShulkerBox extends CraftLootable implements ShulkerBox, CraftLootableBlockInventory { // Paper
|
|
|
|
private final CraftWorld world;
|
|
private final TileEntityShulkerBox box;
|
|
@@ -31,7 +32,7 @@ public class CraftShulkerBox extends CraftLootable implements ShulkerBox {
|
|
}
|
|
|
|
@Override
|
|
- public TileEntity getTileEntity() {
|
|
+ public TileEntityShulkerBox getTileEntity() { // Paper
|
|
return box;
|
|
}
|
|
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java
|
|
index 69435c457..4291edf25 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java
|
|
@@ -1,5 +1,6 @@
|
|
package org.bukkit.craftbukkit.entity;
|
|
|
|
+import com.destroystokyo.paper.loottable.CraftLootableEntityInventory; // Paper
|
|
import net.minecraft.server.EntityMinecartChest;
|
|
|
|
import org.bukkit.craftbukkit.CraftServer;
|
|
@@ -9,7 +10,7 @@ import org.bukkit.entity.minecart.StorageMinecart;
|
|
import org.bukkit.inventory.Inventory;
|
|
|
|
@SuppressWarnings("deprecation")
|
|
-public class CraftMinecartChest extends CraftMinecart implements StorageMinecart {
|
|
+public class CraftMinecartChest extends CraftMinecart implements StorageMinecart, CraftLootableEntityInventory { // Paper
|
|
private final CraftInventory inventory;
|
|
|
|
public CraftMinecartChest(CraftServer server, EntityMinecartChest entity) {
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java
|
|
index e9963e21c..acb4dee04 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java
|
|
@@ -1,5 +1,6 @@
|
|
package org.bukkit.craftbukkit.entity;
|
|
|
|
+import com.destroystokyo.paper.loottable.CraftLootableEntityInventory; // Paper
|
|
import net.minecraft.server.EntityMinecartHopper;
|
|
|
|
import org.bukkit.craftbukkit.CraftServer;
|
|
@@ -8,7 +9,7 @@ import org.bukkit.entity.EntityType;
|
|
import org.bukkit.entity.minecart.HopperMinecart;
|
|
import org.bukkit.inventory.Inventory;
|
|
|
|
-final class CraftMinecartHopper extends CraftMinecart implements HopperMinecart {
|
|
+final class CraftMinecartHopper extends CraftMinecart implements HopperMinecart, CraftLootableEntityInventory { // Paper
|
|
private final CraftInventory inventory;
|
|
|
|
CraftMinecartHopper(CraftServer server, EntityMinecartHopper entity) {
|
|
--
|
|
2.12.2.windows.2
|
|
|