mirror of
https://github.com/PaperMC/Paper.git
synced 2024-11-08 11:50:32 +01:00
211cba970b
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" API and Event added to control the Auto Replenish feature for players.
702 lines
26 KiB
Diff
702 lines
26 KiB
Diff
From 82ffa4af43c27227820035be39705b4a233087c2 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 9a9e2eb..3612701 100644
|
|
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
@@ -339,4 +339,26 @@ public class PaperWorldConfig {
|
|
this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax);
|
|
this.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 0000000..36c36d1
|
|
--- /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 0000000..042fc6f
|
|
--- /dev/null
|
|
+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableBlockInventory.java
|
|
@@ -0,0 +1,28 @@
|
|
+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 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 0000000..6407c58
|
|
--- /dev/null
|
|
+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableEntityInventory.java
|
|
@@ -0,0 +1,26 @@
|
|
+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();
|
|
+
|
|
+ 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 0000000..87917d5
|
|
--- /dev/null
|
|
+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventory.java
|
|
@@ -0,0 +1,87 @@
|
|
+package com.destroystokyo.paper.loottable;
|
|
+
|
|
+import org.apache.commons.lang.Validate;
|
|
+
|
|
+import java.util.UUID;
|
|
+
|
|
+public interface CraftLootableInventory extends CraftLootable, LootableInventory {
|
|
+
|
|
+ CraftLootableInventoryData getLootableData();
|
|
+
|
|
+ @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 0000000..4b2c3fd
|
|
--- /dev/null
|
|
+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventoryData.java
|
|
@@ -0,0 +1,179 @@
|
|
+package com.destroystokyo.paper.loottable;
|
|
+
|
|
+import com.destroystokyo.paper.PaperWorldConfig;
|
|
+import net.minecraft.server.*;
|
|
+import org.bukkit.entity.Player;
|
|
+
|
|
+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(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);
|
|
+ if (paperConfig.restrictPlayerReloot && hasPlayerLooted(player.getUniqueID())) {
|
|
+ event.setCancelled(true);
|
|
+ }
|
|
+ return event.callEvent();
|
|
+ }
|
|
+ public void processRefill(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);
|
|
+ }
|
|
+ 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 56e7de8..51b29c8 100644
|
|
--- a/src/main/java/net/minecraft/server/EntityMinecartContainer.java
|
|
+++ b/src/main/java/net/minecraft/server/EntityMinecartContainer.java
|
|
@@ -3,17 +3,20 @@ package net.minecraft.server;
|
|
import java.util.Random;
|
|
// CraftBukkit start
|
|
import java.util.List;
|
|
+
|
|
+import com.destroystokyo.paper.loottable.CraftLootableInventoryData; // Paper
|
|
+import com.destroystokyo.paper.loottable.CraftLootableInventory; // 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 ItemStack[] items = new ItemStack[27]; // CraftBukkit - 36 -> 27
|
|
private boolean b = true;
|
|
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>();
|
|
@@ -130,6 +133,7 @@ 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) {
|
|
@@ -156,6 +160,7 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp
|
|
protected void a(NBTTagCompound nbttagcompound) {
|
|
super.a(nbttagcompound);
|
|
this.items = new ItemStack[this.getSize()];
|
|
+ lootableData.loadNbt(nbttagcompound); // Paper
|
|
if (nbttagcompound.hasKeyOfType("LootTable", 8)) {
|
|
this.c = new MinecraftKey(nbttagcompound.getString("LootTable"));
|
|
this.d = nbttagcompound.getLong("LootTableSeed");
|
|
@@ -217,10 +222,10 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp
|
|
}
|
|
|
|
public void f(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) {
|
|
@@ -249,12 +254,42 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp
|
|
|
|
}
|
|
|
|
+ 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 CraftLootableInventoryData lootableData = new CraftLootableInventoryData(this);
|
|
+
|
|
+ @Override
|
|
+ public CraftLootableInventoryData getLootableData() {
|
|
+ return lootableData;
|
|
+ }
|
|
+
|
|
+ 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 437ac1e..2df98ff 100644
|
|
--- a/src/main/java/net/minecraft/server/TileEntityLootable.java
|
|
+++ b/src/main/java/net/minecraft/server/TileEntityLootable.java
|
|
@@ -1,15 +1,19 @@
|
|
package net.minecraft.server;
|
|
|
|
+import com.destroystokyo.paper.loottable.CraftLootableInventoryData; // Paper
|
|
+import com.destroystokyo.paper.loottable.CraftLootableInventory; // Paper
|
|
+
|
|
import java.util.Random;
|
|
|
|
-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
|
|
|
|
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");
|
|
@@ -20,6 +24,7 @@ public abstract class TileEntityLootable extends TileEntityContainer implements
|
|
}
|
|
|
|
protected boolean d(NBTTagCompound nbttagcompound) {
|
|
+ lootableData.saveNbt(nbttagcompound); // Paper
|
|
if (this.m != null) {
|
|
nbttagcompound.setString("LootTable", this.m.toString());
|
|
if (this.n != 0L) {
|
|
@@ -33,10 +38,10 @@ public abstract class TileEntityLootable extends TileEntityContainer implements
|
|
}
|
|
|
|
protected void d(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) {
|
|
@@ -56,12 +61,46 @@ 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;
|
|
}
|
|
+
|
|
+ // Paper start - LootTable API
|
|
+ private CraftLootableInventoryData lootableData = new CraftLootableInventoryData(this);
|
|
+
|
|
+ @Override
|
|
+ public CraftLootableInventoryData getLootableData() {
|
|
+ return lootableData;
|
|
+ }
|
|
+
|
|
+ @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 ce36ee4..99b039b 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 CraftBlockState implements Chest {
|
|
+public class CraftChest extends CraftBlockState 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 a3ca3a5..cd7e65d 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 CraftBlockState implements Dispenser {
|
|
+public class CraftDispenser extends CraftBlockState 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 db844a3..1e805a7 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 CraftBlockState implements Hopper {
|
|
+public class CraftHopper extends CraftBlockState implements Hopper, CraftLootableBlockInventory { // Paper
|
|
private final TileEntityHopper hopper;
|
|
|
|
public CraftHopper(final Block block) {
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java
|
|
index f5a1875..b2c5679 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.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 38a5e02..0ccc616 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.8.2
|
|
|