2018-07-24 08:24:44 +08:00
From 5adbcec5141acf1e524b36ac8667998cff3f10d8 Mon Sep 17 00:00:00 2001
2016-05-02 11:54:08 +08:00
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
2018-07-24 08:24:44 +08:00
index 8d54af6bb..a3823408c 100644
2016-05-02 11:54:08 +08:00
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
2018-07-24 08:24:44 +08:00
@@ -254,4 +254,26 @@ public class PaperWorldConfig {
2016-05-02 11:54:08 +08:00
this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax);
2017-03-25 11:18:58 +08:00
log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax);
2016-05-02 11:54:08 +08:00
}
+
+ 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
2018-02-13 08:44:50 +08:00
index 000000000..36c36d158
2016-05-02 11:54:08 +08:00
--- /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
2018-02-13 08:44:50 +08:00
index 000000000..20d236c45
2016-05-02 11:54:08 +08:00
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableBlockInventory.java
2016-05-08 09:16:38 +08:00
@@ -0,0 +1,33 @@
2016-05-02 11:54:08 +08:00
+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
2016-05-08 09:16:38 +08:00
+ default LootableInventory getAPILootableInventory() {
+ return this;
+ }
+
+ @Override
2016-05-02 11:54:08 +08:00
+ 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
2018-02-13 08:44:50 +08:00
index 000000000..1150dee01
2016-05-02 11:54:08 +08:00
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableEntityInventory.java
2016-05-08 09:16:38 +08:00
@@ -0,0 +1,31 @@
2016-05-02 11:54:08 +08:00
+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();
+
2016-05-08 09:16:38 +08:00
+ @Override
+ default LootableInventory getAPILootableInventory() {
+ return this;
+ }
+
2016-05-02 11:54:08 +08:00
+ 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
2018-02-13 08:44:50 +08:00
index 000000000..668097620
2016-05-02 11:54:08 +08:00
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventory.java
2016-05-08 09:16:38 +08:00
@@ -0,0 +1,88 @@
2016-05-02 11:54:08 +08:00
+package com.destroystokyo.paper.loottable;
+
+import org.apache.commons.lang.Validate;
+
+import java.util.UUID;
+
+public interface CraftLootableInventory extends CraftLootable, LootableInventory {
+
+ CraftLootableInventoryData getLootableData();
2016-05-08 09:16:38 +08:00
+ LootableInventory getAPILootableInventory();
2016-05-02 11:54:08 +08:00
+
+ @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
2018-07-16 23:34:55 +08:00
index 000000000..9a65603bc
2016-05-02 11:54:08 +08:00
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventoryData.java
2016-05-15 14:41:36 +08:00
@@ -0,0 +1,182 @@
2016-05-02 11:54:08 +08:00
+package com.destroystokyo.paper.loottable;
+
+import com.destroystokyo.paper.PaperWorldConfig;
+import net.minecraft.server.*;
+import org.bukkit.entity.Player;
+
2016-05-12 10:07:46 +08:00
+import javax.annotation.Nullable;
2016-05-02 11:54:08 +08:00
+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;
+ }
+
2016-05-12 10:07:46 +08:00
+ public boolean shouldReplenish(@Nullable EntityHuman player) {
2016-05-02 11:54:08 +08:00
+ 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();
2016-05-08 09:16:38 +08:00
+ LootableInventoryReplenishEvent event = new LootableInventoryReplenishEvent(bukkitPlayer, lootable.getAPILootableInventory());
2016-05-02 11:54:08 +08:00
+ if (paperConfig.restrictPlayerReloot && hasPlayerLooted(player.getUniqueID())) {
+ event.setCancelled(true);
+ }
+ return event.callEvent();
+ }
2016-05-15 14:41:36 +08:00
+ public void processRefill(@Nullable EntityHuman player) {
2016-05-02 11:54:08 +08:00
+ this.lastFill = System.currentTimeMillis();
+ final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig;
+ if (paperConfig.autoReplenishLootables) {
2018-06-14 02:15:31 +08:00
+ int min = paperConfig.lootableRegenMin;
+ int max = paperConfig.lootableRegenMax;
+ this.nextRefill = this.lastFill + (min + RANDOM.nextInt(max - min + 1)) * 1000L;
2016-05-02 11:54:08 +08:00
+ this.numRefills++;
+ if (paperConfig.changeLootTableSeedOnFill) {
+ this.lootable.setLootTableSeed(0);
+ }
2016-05-15 14:41:36 +08:00
+ 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);
+ }
2016-05-02 11:54:08 +08:00
+ } 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++) {
2018-07-16 23:34:55 +08:00
+ final NBTTagCompound cmp = list.getCompound(i);
2016-05-02 11:54:08 +08:00
+ 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
2018-07-24 08:24:44 +08:00
index 9ec73ac06..8bd7976f9 100644
2016-05-02 11:54:08 +08:00
--- a/src/main/java/net/minecraft/server/EntityMinecartContainer.java
+++ b/src/main/java/net/minecraft/server/EntityMinecartContainer.java
2016-11-17 10:23:38 +08:00
@@ -6,17 +6,21 @@ import javax.annotation.Nullable;
2016-05-02 11:54:08 +08:00
// CraftBukkit start
import java.util.List;
2016-05-12 10:07:46 +08:00
import org.bukkit.Location;
2016-05-02 11:54:08 +08:00
+
+import com.destroystokyo.paper.loottable.CraftLootableInventoryData; // Paper
+import com.destroystokyo.paper.loottable.CraftLootableInventory; // Paper
2016-05-08 09:16:38 +08:00
+import com.destroystokyo.paper.loottable.LootableInventory; // Paper
2016-05-02 11:54:08 +08:00
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
2016-11-17 10:23:38 +08:00
private NonNullList<ItemStack> items;
private boolean b;
2016-05-02 11:54:08 +08:00
private MinecraftKey c;
- private long d;
2016-07-28 06:46:02 +08:00
+ private long d;public long getLootTableSeed() { return d; } // Paper - OBFHELPER
2016-05-02 11:54:08 +08:00
// CraftBukkit start
public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
2018-07-22 13:27:46 +08:00
@@ -168,12 +172,13 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp
2016-05-02 11:54:08 +08:00
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) {
2016-06-07 07:56:51 +08:00
nbttagcompound.setLong("LootTableSeed", this.d);
}
- } else {
+ } if (true) { // Paper - Always save the items, Table may stick around
2016-11-17 10:23:38 +08:00
ContainerUtil.a(nbttagcompound, this.items);
}
2016-06-07 07:56:51 +08:00
2018-07-22 13:27:46 +08:00
@@ -181,11 +186,12 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp
2017-06-21 06:59:18 +08:00
protected void a(NBTTagCompound nbttagcompound) {
super.a(nbttagcompound);
+ lootableData.loadNbt(nbttagcompound); // Paper
this.items = NonNullList.a(this.getSize(), ItemStack.a);
2016-05-02 11:54:08 +08:00
if (nbttagcompound.hasKeyOfType("LootTable", 8)) {
this.c = new MinecraftKey(nbttagcompound.getString("LootTable"));
this.d = nbttagcompound.getLong("LootTableSeed");
2016-06-07 07:56:51 +08:00
- } else {
+ } if (true) { // Paper - always load the items, table may still remain
2016-11-17 10:23:38 +08:00
ContainerUtil.b(nbttagcompound, this.items);
}
2016-06-07 07:56:51 +08:00
2018-07-22 13:27:46 +08:00
@@ -234,10 +240,10 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp
2016-05-02 11:54:08 +08:00
}
2016-05-12 10:07:46 +08:00
public void f(@Nullable EntityHuman entityhuman) {
2018-07-16 23:34:55 +08:00
- if (this.c != null && this.world.getMinecraftServer() != null) {
+ if (lootableData.shouldReplenish(entityhuman) && this.world.getMinecraftServer() != null) { // Paper
LootTable loottable = this.world.getMinecraftServer().aP().a(this.c);
2016-05-02 11:54:08 +08:00
- this.c = null;
+ lootableData.processRefill(entityhuman); // Paper
Random random;
if (this.d == 0L) {
2018-07-22 13:27:46 +08:00
@@ -262,12 +268,51 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp
2016-11-17 10:23:38 +08:00
this.items.clear();
2016-05-02 11:54:08 +08:00
}
2016-07-28 06:46:02 +08:00
+ public void setLootTable(MinecraftKey key, long seed) { a(key, seed);} // Paper - OBFHELPER
2016-05-02 11:54:08 +08:00
public void a(MinecraftKey minecraftkey, long i) {
this.c = minecraftkey;
this.d = i;
}
2018-07-16 23:34:55 +08:00
+ public MinecraftKey getLootTableKey() { return Q_(); } // Paper - OBFHELPER
public MinecraftKey Q_() {
2016-05-02 11:54:08 +08:00
return this.c;
}
+
+ // Paper start
2016-05-08 09:16:38 +08:00
+ private final CraftLootableInventoryData lootableData = new CraftLootableInventoryData(this);
2016-05-02 11:54:08 +08:00
+
+ @Override
+ public CraftLootableInventoryData getLootableData() {
+ return lootableData;
+ }
+
2016-05-05 08:33:16 +08:00
+ @Override
2016-05-08 09:16:38 +08:00
+ public LootableInventory getAPILootableInventory() {
+ return (LootableInventory) this.getBukkitEntity();
+ }
+
+ @Override
2016-05-05 08:33:16 +08:00
+ public World getNMSWorld() {
+ return this.world;
+ }
+
2016-05-02 11:54:08 +08:00
+ 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
2018-07-24 08:24:44 +08:00
index fbda02b32..e6fc1ae92 100644
2016-05-02 11:54:08 +08:00
--- a/src/main/java/net/minecraft/server/TileEntityLootable.java
+++ b/src/main/java/net/minecraft/server/TileEntityLootable.java
2018-07-16 23:34:55 +08:00
@@ -1,12 +1,16 @@
2016-05-02 11:54:08 +08:00
package net.minecraft.server;
+import com.destroystokyo.paper.loottable.CraftLootableInventoryData; // Paper
+import com.destroystokyo.paper.loottable.CraftLootableInventory; // Paper
2016-05-08 09:16:38 +08:00
+import com.destroystokyo.paper.loottable.LootableInventory; // Paper
2016-05-02 11:54:08 +08:00
+
import java.util.Random;
2016-05-12 10:07:46 +08:00
import javax.annotation.Nullable;
2016-05-02 11:54:08 +08:00
-public abstract class TileEntityLootable extends TileEntityContainer implements ILootable {
+public abstract class TileEntityLootable extends TileEntityContainer implements ILootable, CraftLootableInventory { // Paper
2018-07-16 23:34:55 +08:00
protected MinecraftKey g;
- protected long h;
+ protected long h; public long getLootTableSeed() { return h; } // Paper - OBFHELPER
protected IChatBaseComponent i;
2016-05-02 11:54:08 +08:00
2018-07-16 23:34:55 +08:00
protected TileEntityLootable(TileEntityTypes<?> tileentitytypes) {
@@ -23,16 +27,18 @@ public abstract class TileEntityLootable extends TileEntityContainer implements
}
2016-05-02 11:54:08 +08:00
2018-07-16 23:34:55 +08:00
protected boolean d(NBTTagCompound nbttagcompound) {
2016-05-02 11:54:08 +08:00
+ lootableData.loadNbt(nbttagcompound); // Paper
if (nbttagcompound.hasKeyOfType("LootTable", 8)) {
2018-07-16 23:34:55 +08:00
this.g = new MinecraftKey(nbttagcompound.getString("LootTable"));
this.h = nbttagcompound.getLong("LootTableSeed");
2016-06-07 15:03:51 +08:00
- return true;
+ return false; // Paper - always load the items, table may still remain
2016-06-07 07:56:51 +08:00
} else {
2016-06-07 15:03:51 +08:00
return false;
2016-06-07 07:56:51 +08:00
}
2016-05-02 11:54:08 +08:00
}
2018-07-16 23:34:55 +08:00
protected boolean e(NBTTagCompound nbttagcompound) {
2016-05-02 11:54:08 +08:00
+ lootableData.saveNbt(nbttagcompound); // Paper
2018-07-16 23:34:55 +08:00
if (this.g == null) {
return false;
} else {
@@ -41,15 +47,15 @@ public abstract class TileEntityLootable extends TileEntityContainer implements
nbttagcompound.setLong("LootTableSeed", this.h);
2016-06-07 15:03:51 +08:00
}
2016-06-07 07:56:51 +08:00
2016-06-07 15:03:51 +08:00
- return true;
+ return false; // Paper - always save the items, table may still remain
2016-06-07 07:56:51 +08:00
}
2016-05-02 11:54:08 +08:00
}
2016-11-17 10:23:38 +08:00
public void d(@Nullable EntityHuman entityhuman) {
2018-07-16 23:34:55 +08:00
- if (this.g != null && this.world.getMinecraftServer() != null) {
+ if (lootableData.shouldReplenish(entityhuman) && this.world.getMinecraftServer() != null) { // Paper
LootTable loottable = this.world.getMinecraftServer().aP().a(this.g);
2016-05-02 11:54:08 +08:00
2018-07-16 23:34:55 +08:00
- this.g = null;
2016-05-02 11:54:08 +08:00
+ lootableData.processRefill(entityhuman); // Paper
Random random;
2018-07-16 23:34:55 +08:00
if (this.h == 0L) {
@@ -70,10 +76,12 @@ public abstract class TileEntityLootable extends TileEntityContainer implements
2016-05-02 11:54:08 +08:00
}
2018-07-16 23:34:55 +08:00
+ public MinecraftKey getLootTableKey() { return Q_(); } // Paper - OBFHELPER
public MinecraftKey Q_() {
return this.g;
2016-05-02 11:54:08 +08:00
}
2016-07-28 06:46:02 +08:00
+ public void setLootTable(MinecraftKey key, long seed) { a(key, seed);} // Paper - OBFHELPER
2016-05-02 11:54:08 +08:00
public void a(MinecraftKey minecraftkey, long i) {
2018-07-16 23:34:55 +08:00
this.g = minecraftkey;
this.h = i;
@@ -152,4 +160,41 @@ public abstract class TileEntityLootable extends TileEntityContainer implements
2016-11-17 10:23:38 +08:00
protected abstract NonNullList<ItemStack> q();
2018-07-16 23:34:55 +08:00
protected abstract void a(NonNullList<ItemStack> nonnulllist);
2016-05-02 11:54:08 +08:00
+ // Paper start - LootTable API
2016-05-08 09:16:38 +08:00
+ private final CraftLootableInventoryData lootableData = new CraftLootableInventoryData(this);
2016-05-02 11:54:08 +08:00
+
+ @Override
+ public CraftLootableInventoryData getLootableData() {
+ return lootableData;
+ }
+
+ @Override
2016-05-08 09:16:38 +08:00
+ public LootableInventory getAPILootableInventory() {
+ return (LootableInventory) getBukkitWorld().getBlockAt(MCUtil.toLocation(world, getPosition())).getState();
+ }
+
+ @Override
2016-05-02 11:54:08 +08:00
+ 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
2018-07-16 23:34:55 +08:00
+ this.g = (MinecraftKey) null;
2016-05-02 11:54:08 +08:00
+ }
+ // Paper end
2016-11-17 10:23:38 +08:00
+
2016-05-02 11:54:08 +08:00
}
2017-08-06 06:36:47 +08:00
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
2018-07-16 23:34:55 +08:00
index ac9b4297b..0558cafe3 100644
2017-08-06 06:36:47 +08:00
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
2018-07-16 23:34:55 +08:00
@@ -61,7 +61,7 @@ public class CraftBlockEntityState<T extends TileEntity> extends CraftBlockState
2017-08-06 06:36:47 +08:00
}
// gets the wrapped TileEntity
- protected T getTileEntity() {
+ public T getTileEntity() { // Paper - protected -> public
return tileEntity;
}
2016-05-02 11:54:08 +08:00
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
2018-07-16 23:34:55 +08:00
index 6a54f2a16..a94c78512 100644
2016-05-02 11:54:08 +08:00
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
2018-07-16 23:34:55 +08:00
@@ -1,6 +1,7 @@
2016-05-02 11:54:08 +08:00
package org.bukkit.craftbukkit.block;
2018-07-16 23:34:55 +08:00
import net.minecraft.server.BlockChest;
2016-05-02 11:54:08 +08:00
+import com.destroystokyo.paper.loottable.CraftLootableBlockInventory; // Paper
import net.minecraft.server.BlockPosition;
2018-07-16 23:34:55 +08:00
import net.minecraft.server.Blocks;
import net.minecraft.server.ITileInventory;
@@ -15,7 +16,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventory;
2016-05-02 11:54:08 +08:00
import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest;
import org.bukkit.inventory.Inventory;
2017-08-06 06:36:47 +08:00
-public class CraftChest extends CraftLootable<TileEntityChest> implements Chest {
+public class CraftChest extends CraftLootable<TileEntityChest> implements Chest, CraftLootableBlockInventory { // Paper
2016-05-02 11:54:08 +08:00
2017-08-06 06:36:47 +08:00
public CraftChest(final Block block) {
super(block, TileEntityChest.class);
2016-05-02 11:54:08 +08:00
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java b/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java
2018-02-13 08:44:50 +08:00
index 1dc8bfecd..bfcf9b6c4 100644
2016-05-02 11:54:08 +08:00
--- 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;
2017-08-06 06:36:47 +08:00
-public class CraftDispenser extends CraftLootable<TileEntityDispenser> implements Dispenser {
+public class CraftDispenser extends CraftLootable<TileEntityDispenser> implements Dispenser, CraftLootableBlockInventory {
2016-05-02 11:54:08 +08:00
2017-08-06 06:36:47 +08:00
public CraftDispenser(final Block block) {
super(block, TileEntityDispenser.class);
2016-05-02 11:54:08 +08:00
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java b/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java
2018-02-13 08:44:50 +08:00
index 6566554ab..df156d0d9 100644
2016-05-02 11:54:08 +08:00
--- 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;
2017-08-06 06:36:47 +08:00
@@ -7,7 +8,7 @@ import org.bukkit.block.Hopper;
2016-05-02 11:54:08 +08:00
import org.bukkit.craftbukkit.inventory.CraftInventory;
import org.bukkit.inventory.Inventory;
2017-08-06 06:36:47 +08:00
-public class CraftHopper extends CraftLootable<TileEntityHopper> implements Hopper {
+public class CraftHopper extends CraftLootable<TileEntityHopper> implements Hopper, CraftLootableBlockInventory {
2016-05-02 11:54:08 +08:00
public CraftHopper(final Block block) {
2017-08-06 06:36:47 +08:00
super(block, TileEntityHopper.class);
2016-11-20 01:31:01 +08:00
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java b/src/main/java/org/bukkit/craftbukkit/block/CraftShulkerBox.java
2018-02-13 08:44:50 +08:00
index c029a1244..c26f0b5af 100644
2016-11-20 01:31:01 +08:00
--- 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.TileEntityShulkerBox;
2017-08-06 06:36:47 +08:00
import org.bukkit.DyeColor;
@@ -10,7 +11,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventory;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
2016-11-20 01:31:01 +08:00
import org.bukkit.inventory.Inventory;
2017-08-06 06:36:47 +08:00
-public class CraftShulkerBox extends CraftLootable<TileEntityShulkerBox> implements ShulkerBox {
+public class CraftShulkerBox extends CraftLootable<TileEntityShulkerBox> implements ShulkerBox, CraftLootableBlockInventory {
2016-11-20 01:31:01 +08:00
2017-08-06 06:36:47 +08:00
public CraftShulkerBox(final Block block) {
super(block, TileEntityShulkerBox.class);
2016-05-02 11:54:08 +08:00
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java
2018-02-13 08:44:50 +08:00
index 69435c457..4291edf25 100644
2016-05-02 11:54:08 +08:00
--- 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;
2016-11-17 10:23:38 +08:00
@@ -9,7 +10,7 @@ import org.bukkit.entity.minecart.StorageMinecart;
2016-05-02 11:54:08 +08:00
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
2018-02-13 08:44:50 +08:00
index e9963e21c..acb4dee04 100644
2016-05-02 11:54:08 +08:00
--- 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) {
--
2018-07-19 12:42:43 +08:00
2.18.0
2016-05-02 11:54:08 +08:00