2020-05-06 11:48:49 +02:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2016-05-02 05:54:08 +02: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
2021-01-11 02:44:06 +01:00
index 5baccb8d50c135ab20c38ffd0690f585514ce5af..eb04fdb172a50ec1f5b7fe78fa0e7655246abd60 100644
2016-05-02 05:54:08 +02:00
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
2021-01-11 02:44:06 +01:00
@@ -269,4 +269,26 @@ public class PaperWorldConfig {
2016-05-02 05:54:08 +02:00
this.frostedIceDelayMax = this.getInt("frosted-ice.delay.max", this.frostedIceDelayMax);
2017-03-25 04:18:58 +01:00
log("Frosted Ice: " + (this.frostedIceEnabled ? "enabled" : "disabled") + " / delay: min=" + this.frostedIceDelayMin + ", max=" + this.frostedIceDelayMax);
2016-05-02 05:54:08 +02: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)" : "")
+ );
+ }
+ }
}
2018-08-26 20:11:49 +02:00
diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java
2016-05-02 05:54:08 +02:00
new file mode 100644
2020-05-06 11:48:49 +02:00
index 0000000000000000000000000000000000000000..d6fce3112ebd8ef208c6fe45e0d887ec778fc092
2016-05-02 05:54:08 +02:00
--- /dev/null
2018-08-26 20:11:49 +02:00
+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableBlockInventory.java
2016-05-08 03:16:38 +02:00
@@ -0,0 +1,33 @@
2016-05-02 05:54:08 +02: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;
+
2018-08-26 20:11:49 +02:00
+public interface PaperLootableBlockInventory extends LootableBlockInventory, PaperLootableInventory {
2016-05-02 05:54:08 +02:00
+
+ TileEntityLootable getTileEntity();
+
+ @Override
2016-05-08 03:16:38 +02:00
+ default LootableInventory getAPILootableInventory() {
+ return this;
+ }
+
+ @Override
2016-05-02 05:54:08 +02: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
2018-08-26 20:11:49 +02:00
+ default PaperLootableInventoryData getLootableData() {
+ return getTileEntity().lootableData;
2016-05-02 05:54:08 +02:00
+ }
+}
2018-08-26 20:11:49 +02:00
diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java
2016-05-02 05:54:08 +02:00
new file mode 100644
2020-05-06 11:48:49 +02:00
index 0000000000000000000000000000000000000000..5e637782d555cd68952e8bdbd47a63a636348ec6
2016-05-02 05:54:08 +02:00
--- /dev/null
2018-08-26 20:11:49 +02:00
+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableEntityInventory.java
@@ -0,0 +1,28 @@
2016-05-02 05:54:08 +02:00
+package com.destroystokyo.paper.loottable;
+
+import net.minecraft.server.World;
+import org.bukkit.entity.Entity;
+
2018-08-26 20:11:49 +02:00
+public interface PaperLootableEntityInventory extends LootableEntityInventory, PaperLootableInventory {
2016-05-02 05:54:08 +02:00
+
+ net.minecraft.server.Entity getHandle();
+
2016-05-08 03:16:38 +02:00
+ @Override
+ default LootableInventory getAPILootableInventory() {
+ return this;
+ }
+
2016-05-02 05:54:08 +02:00
+ default Entity getEntity() {
+ return getHandle().getBukkitEntity();
+ }
+
+ @Override
+ default World getNMSWorld() {
+ return getHandle().getWorld();
+ }
+
+ @Override
2018-08-26 20:11:49 +02:00
+ default PaperLootableInventoryData getLootableData() {
+ return getHandle().lootableData;
2016-05-02 05:54:08 +02:00
+ }
+}
2018-08-26 20:11:49 +02:00
diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java
2016-05-02 05:54:08 +02:00
new file mode 100644
2020-05-06 11:48:49 +02:00
index 0000000000000000000000000000000000000000..856843fc917ff6a7252b7900f7772cc9debe3649
2016-05-02 05:54:08 +02:00
--- /dev/null
2018-08-26 20:11:49 +02:00
+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventory.java
@@ -0,0 +1,71 @@
2016-05-02 05:54:08 +02:00
+package com.destroystokyo.paper.loottable;
+
2018-08-26 20:11:49 +02:00
+import net.minecraft.server.World;
+import org.bukkit.loot.Lootable;
+
2016-05-02 05:54:08 +02:00
+import java.util.UUID;
+
2018-08-26 20:11:49 +02:00
+public interface PaperLootableInventory extends LootableInventory, Lootable {
2016-05-02 05:54:08 +02:00
+
2018-08-26 20:11:49 +02:00
+ PaperLootableInventoryData getLootableData();
2016-05-08 03:16:38 +02:00
+ LootableInventory getAPILootableInventory();
2016-05-02 05:54:08 +02:00
+
2018-08-26 20:11:49 +02:00
+ World getNMSWorld();
+
+ default org.bukkit.World getBukkitWorld() {
+ return getNMSWorld().getWorld();
+ }
+
2016-05-02 05:54:08 +02:00
+ @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);
+ }
+}
2018-08-26 20:11:49 +02:00
diff --git a/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java
2016-05-02 05:54:08 +02:00
new file mode 100644
2020-05-06 11:48:49 +02:00
index 0000000000000000000000000000000000000000..b5401eaf974857455c17c3f9cfdedf2eb4bde321
2016-05-02 05:54:08 +02:00
--- /dev/null
2018-08-26 20:11:49 +02:00
+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperLootableInventoryData.java
2018-08-12 19:11:08 +02:00
@@ -0,0 +1,179 @@
2016-05-02 05:54:08 +02:00
+package com.destroystokyo.paper.loottable;
+
+import com.destroystokyo.paper.PaperWorldConfig;
+import net.minecraft.server.*;
+import org.bukkit.entity.Player;
2018-08-12 19:11:08 +02:00
+import org.bukkit.loot.LootTable;
2016-05-02 05:54:08 +02:00
+
2016-05-12 04:07:46 +02:00
+import javax.annotation.Nullable;
2016-05-02 05:54:08 +02:00
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+import java.util.UUID;
+
2018-08-26 20:11:49 +02:00
+public class PaperLootableInventoryData {
2016-05-02 05:54:08 +02:00
+
+ private static final Random RANDOM = new Random();
+
+ private long lastFill = -1;
+ private long nextRefill = -1;
+ private int numRefills = 0;
+ private Map<UUID, Long> lootedPlayers;
2018-08-26 20:11:49 +02:00
+ private final PaperLootableInventory lootable;
2016-05-02 05:54:08 +02:00
+
2018-08-26 20:11:49 +02:00
+ public PaperLootableInventoryData(PaperLootableInventory lootable) {
2016-05-02 05:54:08 +02:00
+ 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;
+ }
+
2016-05-12 04:07:46 +02:00
+ public boolean shouldReplenish(@Nullable EntityHuman player) {
2018-08-12 19:11:08 +02:00
+ LootTable table = this.lootable.getLootTable();
2016-05-02 05:54:08 +02:00
+
+ // No Loot Table associated
2018-08-12 19:11:08 +02:00
+ if (table == null) {
2016-05-02 05:54:08 +02:00
+ return false;
+ }
+
2019-02-17 00:22:35 +01:00
+ // ALWAYS process the first fill or if the feature is disabled
+ if (this.lastFill == -1 || !this.lootable.getNMSWorld().paperConfig.autoReplenishLootables) {
2016-05-02 05:54:08 +02:00
+ 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 03:16:38 +02:00
+ LootableInventoryReplenishEvent event = new LootableInventoryReplenishEvent(bukkitPlayer, lootable.getAPILootableInventory());
2016-05-02 05:54:08 +02:00
+ if (paperConfig.restrictPlayerReloot && hasPlayerLooted(player.getUniqueID())) {
+ event.setCancelled(true);
+ }
+ return event.callEvent();
+ }
2016-05-15 08:41:36 +02:00
+ public void processRefill(@Nullable EntityHuman player) {
2016-05-02 05:54:08 +02:00
+ this.lastFill = System.currentTimeMillis();
+ final PaperWorldConfig paperConfig = this.lootable.getNMSWorld().paperConfig;
+ if (paperConfig.autoReplenishLootables) {
2018-06-13 20:15:31 +02:00
+ int min = paperConfig.lootableRegenMin;
+ int max = paperConfig.lootableRegenMax;
+ this.nextRefill = this.lastFill + (min + RANDOM.nextInt(max - min + 1)) * 1000L;
2016-05-02 05:54:08 +02:00
+ this.numRefills++;
+ if (paperConfig.changeLootTableSeedOnFill) {
2018-08-26 20:11:49 +02:00
+ this.lootable.setSeed(0);
2016-05-02 05:54:08 +02:00
+ }
2016-05-15 08:41:36 +02: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 05:54:08 +02: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 17:34:55 +02:00
+ final NBTTagCompound cmp = list.getCompound(i);
2016-05-02 05:54:08 +02: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;
+ }
+}
2018-08-26 20:11:49 +02:00
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
2020-08-02 07:39:36 +02:00
index 0000000000000000000000000000000000000000..8c1fa60a55570be91ab5ea63cb2005caa09e3600
2018-08-26 20:11:49 +02:00
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperMinecartLootableInventory.java
2020-08-02 07:39:36 +02:00
@@ -0,0 +1,63 @@
2018-08-26 20:11:49 +02:00
+package com.destroystokyo.paper.loottable;
+
+import net.minecraft.server.Entity;
+import net.minecraft.server.EntityMinecartContainer;
+import net.minecraft.server.MinecraftKey;
+import net.minecraft.server.World;
2018-08-12 19:11:08 +02:00
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
2018-08-26 20:11:49 +02:00
+
+public class PaperMinecartLootableInventory implements PaperLootableEntityInventory {
+
+ private EntityMinecartContainer entity;
+
+ public PaperMinecartLootableInventory(EntityMinecartContainer entity) {
+ this.entity = entity;
+ }
+
+ @Override
+ public org.bukkit.loot.LootTable getLootTable() {
2020-08-02 07:39:36 +02:00
+ return entity.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(entity.lootTable)) : null;
2018-08-26 20:11:49 +02:00
+ }
+
+ @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) {
2020-08-02 07:39:36 +02:00
+ entity.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey());
2018-08-26 20:11:49 +02:00
+ }
+
+ @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
2020-08-02 07:39:36 +02:00
index 0000000000000000000000000000000000000000..a1923aff2b5e2e867670a5a064a767915fc1cc2a
2018-08-26 20:11:49 +02:00
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/loottable/PaperTileEntityLootableInventory.java
2020-08-02 07:39:36 +02:00
@@ -0,0 +1,66 @@
2018-08-26 20:11:49 +02:00
+package com.destroystokyo.paper.loottable;
+
+import net.minecraft.server.MCUtil;
+import net.minecraft.server.MinecraftKey;
+import net.minecraft.server.TileEntityLootable;
+import net.minecraft.server.World;
+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() {
2020-08-02 07:39:36 +02:00
+ return tileEntityLootable.lootTable != null ? Bukkit.getLootTable(CraftNamespacedKey.fromMinecraft(tileEntityLootable.lootTable)) : null;
2018-08-26 20:11:49 +02:00
+ }
+
+ @Override
+ public void setLootTable(org.bukkit.loot.LootTable table, long seed) {
+ setLootTable(table);
+ setSeed(seed);
+ }
+
+ @Override
+ public void setLootTable(org.bukkit.loot.LootTable table) {
2020-08-02 07:39:36 +02:00
+ tileEntityLootable.lootTable = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey());
2018-08-26 20:11:49 +02:00
+ }
+
+ @Override
+ public void setSeed(long seed) {
2020-08-02 07:39:36 +02:00
+ tileEntityLootable.lootTableSeed = seed;
2018-08-26 20:11:49 +02:00
+ }
+
+ @Override
+ public long getSeed() {
2020-08-02 07:39:36 +02:00
+ return tileEntityLootable.lootTableSeed;
2018-08-26 20:11:49 +02:00
+ }
+
+ @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/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
2021-02-21 20:45:33 +01:00
index dba28796a921beda2e5d15ba1565c55f54e36435..df6377b5849aab20246a29b312744604b4cbf6bf 100644
2018-08-26 20:11:49 +02:00
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
2020-09-11 00:02:39 +02:00
@@ -73,6 +73,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
2019-12-12 00:43:22 +01:00
};
// Paper end
2016-05-02 05:54:08 +02:00
2018-08-26 20:11:49 +02:00
+ public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper
2019-06-03 05:26:25 +02:00
private CraftEntity bukkitEntity;
2018-08-26 20:11:49 +02:00
public CraftEntity getBukkitEntity() {
diff --git a/src/main/java/net/minecraft/server/EntityMinecartContainer.java b/src/main/java/net/minecraft/server/EntityMinecartContainer.java
2020-11-03 03:22:15 +01:00
index 75e9c1538b3d8ef5186986ab3c8ca8b60f63ee6e..574838bd33a46e464ff7d801345613a3351f487f 100644
2018-08-26 20:11:49 +02:00
--- a/src/main/java/net/minecraft/server/EntityMinecartContainer.java
+++ b/src/main/java/net/minecraft/server/EntityMinecartContainer.java
2020-08-02 07:39:36 +02:00
@@ -19,6 +19,7 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp
2018-08-26 20:11:49 +02:00
public long lootTableSeed;
2016-05-02 05:54:08 +02:00
// CraftBukkit start
2019-04-27 05:05:36 +02:00
+ { this.lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperMinecartLootableInventory(this)); } // Paper
2016-05-02 05:54:08 +02:00
public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
2018-08-26 20:11:49 +02:00
private int maxStack = MAX_STACK;
2020-08-25 04:22:08 +02:00
@@ -176,12 +177,13 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp
2019-04-27 05:05:36 +02:00
@Override
2020-06-25 13:00:35 +02:00
protected void saveData(NBTTagCompound nbttagcompound) {
super.saveData(nbttagcompound);
2019-04-27 05:05:36 +02:00
+ this.lootableData.saveNbt(nbttagcompound); // Paper
if (this.lootTable != null) {
nbttagcompound.setString("LootTable", this.lootTable.toString());
2018-08-26 20:11:49 +02:00
if (this.lootTableSeed != 0L) {
nbttagcompound.setLong("LootTableSeed", this.lootTableSeed);
2016-06-07 01:56:51 +02:00
}
- } else {
+ } if (true) { // Paper - Always save the items, Table may stick around
2016-11-17 03:23:38 +01:00
ContainerUtil.a(nbttagcompound, this.items);
}
2016-06-07 01:56:51 +02:00
2020-08-25 04:22:08 +02:00
@@ -190,11 +192,12 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp
2019-04-27 05:05:36 +02:00
@Override
2020-06-25 13:00:35 +02:00
protected void loadData(NBTTagCompound nbttagcompound) {
super.loadData(nbttagcompound);
2019-04-27 05:05:36 +02:00
+ this.lootableData.loadNbt(nbttagcompound); // Paper
2020-06-25 13:00:35 +02:00
this.items = NonNullList.a(this.getSize(), ItemStack.b);
2016-05-02 05:54:08 +02:00
if (nbttagcompound.hasKeyOfType("LootTable", 8)) {
2019-04-27 05:05:36 +02:00
this.lootTable = new MinecraftKey(nbttagcompound.getString("LootTable"));
2018-08-26 20:11:49 +02:00
this.lootTableSeed = nbttagcompound.getLong("LootTableSeed");
2016-06-07 01:56:51 +02:00
- } else {
+ } if (true) { // Paper - always load the items, table may still remain
2016-11-17 03:23:38 +01:00
ContainerUtil.b(nbttagcompound, this.items);
}
2016-06-07 01:56:51 +02:00
2020-08-25 04:22:08 +02:00
@@ -225,14 +228,15 @@ public abstract class EntityMinecartContainer extends EntityMinecartAbstract imp
2016-05-02 05:54:08 +02:00
}
2019-04-27 05:05:36 +02:00
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);
2016-05-02 05:54:08 +02:00
2020-06-25 13:00:35 +02:00
if (entityhuman instanceof EntityPlayer) {
2020-07-02 22:34:26 +02:00
CriterionTriggers.N.a((EntityPlayer) entityhuman, this.lootTable);
2020-06-25 13:00:35 +02:00
}
2020-07-02 22:34:26 +02:00
- this.lootTable = null;
+ //this.lootTable = null; // Paper
2019-04-27 05:05:36 +02:00
+ this.lootableData.processRefill(entityhuman); // Paper
2020-08-25 04:22:08 +02:00
LootTableInfo.Builder loottableinfo_builder = (new LootTableInfo.Builder((WorldServer) this.world)).set(LootContextParameters.ORIGIN, this.getPositionVector()).a(this.lootTableSeed);
2016-05-02 05:54:08 +02:00
2019-04-27 05:05:36 +02:00
if (entityhuman != null) {
2016-05-02 05:54:08 +02:00
diff --git a/src/main/java/net/minecraft/server/TileEntityLootable.java b/src/main/java/net/minecraft/server/TileEntityLootable.java
2020-11-03 03:22:15 +01:00
index 9265bc7331f5d3cb43394a7457ab89140b731c8b..d9be182a574daaedcc7a106c759c2bde2e4eb19a 100644
2016-05-02 05:54:08 +02:00
--- a/src/main/java/net/minecraft/server/TileEntityLootable.java
+++ b/src/main/java/net/minecraft/server/TileEntityLootable.java
2020-08-02 07:39:36 +02:00
@@ -8,6 +8,7 @@ public abstract class TileEntityLootable extends TileEntityContainer {
2019-04-27 05:05:36 +02:00
@Nullable
2020-08-02 07:39:36 +02:00
public MinecraftKey lootTable;
public long lootTableSeed;
2018-08-26 20:11:49 +02:00
+ public final com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData = new com.destroystokyo.paper.loottable.PaperLootableInventoryData(new com.destroystokyo.paper.loottable.PaperTileEntityLootableInventory(this)); // Paper
2016-05-02 05:54:08 +02:00
2018-07-16 17:34:55 +02:00
protected TileEntityLootable(TileEntityTypes<?> tileentitytypes) {
2018-08-26 20:11:49 +02:00
super(tileentitytypes);
2020-11-03 03:22:15 +01:00
@@ -23,16 +24,19 @@ public abstract class TileEntityLootable extends TileEntityContainer {
2018-07-16 17:34:55 +02:00
}
2016-05-02 05:54:08 +02:00
2020-06-25 13:00:35 +02:00
protected boolean b(NBTTagCompound nbttagcompound) {
2019-04-27 05:05:36 +02:00
+ this.lootableData.loadNbt(nbttagcompound); // Paper
2016-05-02 05:54:08 +02:00
if (nbttagcompound.hasKeyOfType("LootTable", 8)) {
2019-04-27 05:05:36 +02:00
this.lootTable = new MinecraftKey(nbttagcompound.getString("LootTable"));
2020-11-03 03:22:15 +01:00
+ try { org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(this.lootTable); } catch (IllegalArgumentException ex) { this.lootTable = null; } // Paper - validate
2019-04-27 05:05:36 +02:00
this.lootTableSeed = nbttagcompound.getLong("LootTableSeed");
2016-06-07 09:03:51 +02:00
- return true;
+ return false; // Paper - always load the items, table may still remain
2016-06-07 01:56:51 +02:00
} else {
2016-06-07 09:03:51 +02:00
return false;
2016-06-07 01:56:51 +02:00
}
2016-05-02 05:54:08 +02:00
}
2020-06-25 13:00:35 +02:00
protected boolean c(NBTTagCompound nbttagcompound) {
2019-04-27 05:05:36 +02:00
+ this.lootableData.saveNbt(nbttagcompound); // Paper
if (this.lootTable == null) {
2018-07-16 17:34:55 +02:00
return false;
} else {
2020-11-03 03:22:15 +01:00
@@ -41,19 +45,20 @@ public abstract class TileEntityLootable extends TileEntityContainer {
2019-04-27 05:05:36 +02:00
nbttagcompound.setLong("LootTableSeed", this.lootTableSeed);
2016-06-07 09:03:51 +02:00
}
2016-06-07 01:56:51 +02:00
2016-06-07 09:03:51 +02:00
- return true;
+ return false; // Paper - always save the items, table may still remain
2016-06-07 01:56:51 +02:00
}
2016-05-02 05:54:08 +02:00
}
2016-11-17 03:23:38 +01:00
public void d(@Nullable EntityHuman entityhuman) {
2019-04-27 05:05:36 +02:00
- 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);
2019-01-01 04:15:55 +01:00
2020-06-25 13:00:35 +02:00
if (entityhuman instanceof EntityPlayer) {
2020-07-02 22:34:26 +02:00
CriterionTriggers.N.a((EntityPlayer) entityhuman, this.lootTable);
2020-06-25 13:00:35 +02:00
}
2020-07-02 22:34:26 +02:00
- this.lootTable = null;
+ //this.lootTable = null; // Paper
2019-04-27 05:05:36 +02:00
+ this.lootableData.processRefill(entityhuman); // Paper
2020-08-25 04:22:08 +02:00
LootTableInfo.Builder loottableinfo_builder = (new LootTableInfo.Builder((WorldServer) this.world)).set(LootContextParameters.ORIGIN, Vec3D.a((BaseBlockPosition) this.position)).a(this.lootTableSeed);
2019-01-01 04:15:55 +01:00
2019-04-27 05:05:36 +02:00
if (entityhuman != null) {
2017-08-06 00:36:47 +02:00
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
2021-02-21 20:45:33 +01:00
index da5a80267b189d75374375211a574ca5f18d96be..26cc40e57f5b73b9c32859bff37c4a3d94904c56 100644
2017-08-06 00:36:47 +02:00
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
2019-07-05 04:13:38 +02:00
@@ -64,7 +64,7 @@ public class CraftBlockEntityState<T extends TileEntity> extends CraftBlockState
2017-08-06 00:36:47 +02:00
}
// gets the wrapped TileEntity
- protected T getTileEntity() {
+ public T getTileEntity() { // Paper - protected -> public
return tileEntity;
}
2016-05-02 05:54:08 +02:00
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
2020-08-25 04:22:08 +02:00
index 89df1d7f8b1221014affec459244223491fafaa2..c0fed05d3b68258a61980bdb84fe16dd6adba4c5 100644
2016-05-02 05:54:08 +02:00
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
2020-07-29 21:50:16 +02:00
@@ -12,8 +12,9 @@ import org.bukkit.craftbukkit.CraftWorld;
2018-12-23 18:04:13 +01:00
import org.bukkit.craftbukkit.inventory.CraftInventory;
2016-05-02 05:54:08 +02:00
import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest;
import org.bukkit.inventory.Inventory;
2018-12-23 18:04:13 +01:00
+import com.destroystokyo.paper.loottable.PaperLootableBlockInventory; // Paper
2016-05-02 05:54:08 +02:00
2017-08-06 00:36:47 +02:00
-public class CraftChest extends CraftLootable<TileEntityChest> implements Chest {
2018-08-26 20:11:49 +02:00
+public class CraftChest extends CraftLootable<TileEntityChest> implements Chest, PaperLootableBlockInventory { // Paper
2016-05-02 05:54:08 +02:00
2017-08-06 00:36:47 +02:00
public CraftChest(final Block block) {
super(block, TileEntityChest.class);
2018-08-12 19:11:08 +02:00
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java
2020-05-06 11:48:49 +02:00
index e1ad26a242b9bff8f5a567c24cf58b2150c24144..678aa09d477f653461276e5eab277e1abc253dd8 100644
2018-08-12 19:11:08 +02:00
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftLootable.java
2016-11-19 18:31:01 +01:00
@@ -1,5 +1,6 @@
package org.bukkit.craftbukkit.block;
2018-08-26 20:11:49 +02:00
+import com.destroystokyo.paper.loottable.PaperLootableBlockInventory;
2018-08-12 19:11:08 +02:00
import net.minecraft.server.MinecraftKey;
import net.minecraft.server.TileEntityLootable;
import org.bukkit.Bukkit;
2019-04-27 05:05:36 +02:00
@@ -10,7 +11,7 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey;
2018-08-12 19:11:08 +02:00
import org.bukkit.loot.LootTable;
import org.bukkit.loot.Lootable;
-public abstract class CraftLootable<T extends TileEntityLootable> extends CraftContainer<T> implements Nameable, Lootable {
2018-08-26 20:11:49 +02:00
+public abstract class CraftLootable<T extends TileEntityLootable> extends CraftContainer<T> implements Nameable, Lootable, PaperLootableBlockInventory { // Paper
2018-08-12 19:11:08 +02:00
public CraftLootable(Block block, Class<T> tileEntityClass) {
super(block, tileEntityClass);
2019-04-27 05:05:36 +02:00
@@ -54,7 +55,7 @@ public abstract class CraftLootable<T extends TileEntityLootable> extends CraftC
2018-08-12 19:11:08 +02:00
setLootTable(getLootTable(), seed);
}
2016-11-19 18:31:01 +01:00
2018-08-12 19:11:08 +02:00
- 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());
2018-08-26 20:11:49 +02:00
getSnapshot().setLootTable(key, seed);
2018-08-12 19:11:08 +02:00
}
2016-05-02 05:54:08 +02:00
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java
2020-05-06 11:48:49 +02:00
index e05624e6432f55c3efff3f9d765975557d1be16f..ab4807b2cd3cdcd61d8ac4ae2825df69dd2b7c64 100644
2016-05-02 05:54:08 +02: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;
2018-08-26 20:11:49 +02:00
+import com.destroystokyo.paper.loottable.PaperLootableEntityInventory; // Paper
2016-05-02 05:54:08 +02:00
import net.minecraft.server.EntityMinecartChest;
import org.bukkit.craftbukkit.CraftServer;
2019-04-27 05:05:36 +02:00
import org.bukkit.craftbukkit.inventory.CraftInventory;
@@ -8,7 +9,7 @@ import org.bukkit.entity.minecart.StorageMinecart;
2016-05-02 05:54:08 +02:00
import org.bukkit.inventory.Inventory;
@SuppressWarnings("deprecation")
2018-08-12 19:11:08 +02:00
-public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart {
2018-08-26 20:11:49 +02:00
+public class CraftMinecartChest extends CraftMinecartContainer implements StorageMinecart, PaperLootableEntityInventory { // Paper
2016-05-02 05:54:08 +02:00
private final CraftInventory inventory;
public CraftMinecartChest(CraftServer server, EntityMinecartChest entity) {
2018-08-12 19:11:08 +02:00
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartContainer.java
2020-05-06 11:48:49 +02:00
index 2d776b520bd9b0b8f7475f10e59b02b2ad7b9d8b..fcc9787848c0a0a4025bdf698debf9592c818bff 100644
2018-08-12 19:11:08 +02:00
--- 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
2018-08-26 20:11:49 +02:00
return getHandle().lootTableSeed;
2018-08-12 19:11:08 +02:00
}
- private void setLootTable(LootTable table, long seed) {
2018-08-26 20:11:49 +02:00
+ public void setLootTable(LootTable table, long seed) { // Paper
2018-08-12 19:11:08 +02:00
MinecraftKey newKey = (table == null) ? null : CraftNamespacedKey.toMinecraft(table.getKey());
2019-04-27 05:05:36 +02:00
getHandle().setLootTable(newKey, seed);
2018-08-12 19:11:08 +02:00
}
2016-05-02 05:54:08 +02:00
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java
2020-05-06 11:48:49 +02:00
index 334bd5bb3ffc8b2bcdfca3995cdbe543cee8f311..f5b31237fc6e62345edcc3d6b02ff9e94237ae31 100644
2016-05-02 05:54:08 +02: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;
2018-08-26 20:11:49 +02:00
+import com.destroystokyo.paper.loottable.PaperLootableEntityInventory; // Paper
2016-05-02 05:54:08 +02:00
import net.minecraft.server.EntityMinecartHopper;
import org.bukkit.craftbukkit.CraftServer;
2019-04-27 05:05:36 +02:00
import org.bukkit.craftbukkit.inventory.CraftInventory;
@@ -7,7 +8,7 @@ import org.bukkit.entity.EntityType;
2016-05-02 05:54:08 +02:00
import org.bukkit.entity.minecart.HopperMinecart;
import org.bukkit.inventory.Inventory;
2018-08-12 19:11:08 +02:00
-public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart {
2018-08-26 20:11:49 +02:00
+public final class CraftMinecartHopper extends CraftMinecartContainer implements HopperMinecart, PaperLootableEntityInventory { // Paper
2016-05-02 05:54:08 +02:00
private final CraftInventory inventory;
2018-08-12 19:11:08 +02:00
public CraftMinecartHopper(CraftServer server, EntityMinecartHopper entity) {