mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-27 15:00:13 +01:00
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" API and Event added to control the Auto Replenish feature for players.
This commit is contained in:
parent
4e7355aa95
commit
3da6be053f
7 changed files with 1140 additions and 20 deletions
352
Spigot-API-Patches/LootTable-API.patch
Normal file
352
Spigot-API-Patches/LootTable-API.patch
Normal file
|
@ -0,0 +1,352 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 1 May 2016 15:19:49 -0400
|
||||
Subject: [PATCH] LootTable API
|
||||
|
||||
Provides API to control what Loot Table an object uses.
|
||||
|
||||
Also provides an Event to control if a lootable inventory should
|
||||
auto replenish for a player.
|
||||
|
||||
Provides methods to determine players looted state for an object
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/loottable/Lootable.java b/src/main/java/com/destroystokyo/paper/loottable/Lootable.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/Lootable.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package com.destroystokyo.paper.loottable;
|
||||
+
|
||||
+/**
|
||||
+ * Defines an object that has a Loot Table and seed associated with it.
|
||||
+ *
|
||||
+ * How the Loot Table and seed are used may vary based on Minecraft Versions
|
||||
+ * and what type of object is using the Loot Table
|
||||
+ */
|
||||
+public interface Lootable {
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the name of the Loot Table to be used in the World Folder
|
||||
+ * @return The name, or null if no loot table exists
|
||||
+ */
|
||||
+ String getLootTableName();
|
||||
+
|
||||
+ /**
|
||||
+ * Returns whether or not this object has a Loot Table
|
||||
+ * @return Has a loot table
|
||||
+ */
|
||||
+ default boolean hasLootTable() {
|
||||
+ return getLootTableName() != null;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the name of the Loot Table to be used in the World Folder
|
||||
+ * Will use a random seed (0)
|
||||
+ *
|
||||
+ * @param name name in either foo or minecraft:foo format
|
||||
+ * @return The previous Loot Table before the change
|
||||
+ */
|
||||
+ default String setLootTable(String name) {
|
||||
+ return setLootTable(name, 0);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the name of the Loot Table to be used in the World Folder
|
||||
+ * Uses supplied Seed
|
||||
+ *
|
||||
+ * @param name name in either foo or minecraft:foo format
|
||||
+ * @param seed seed for the loot table. If 0, seed will be random
|
||||
+ * @return The previous Loot Table before the change
|
||||
+ */
|
||||
+ String setLootTable(String name, long seed);
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the current seed associated to the Loot Table on this object
|
||||
+ *
|
||||
+ * @return The seed, or 0 for random
|
||||
+ */
|
||||
+ long getLootTableSeed();
|
||||
+
|
||||
+ /**
|
||||
+ * Changes the current seed associated with the Loot Table on this object.
|
||||
+ *
|
||||
+ * The seed will have no affect if this object does not have a Loot Table
|
||||
+ * associated with it.
|
||||
+ *
|
||||
+ * @throws IllegalStateException If called when this object does not have a loot table
|
||||
+ * @param seed The seed to use, or 0 for random
|
||||
+ * @return The previous seed
|
||||
+ */
|
||||
+ default long setLootTableSeed(long seed) {
|
||||
+ final String lootTableName = getLootTableName();
|
||||
+ if (lootTableName == null) {
|
||||
+ throw new IllegalStateException("This object does not currently have a Loot Table.");
|
||||
+ }
|
||||
+
|
||||
+ long prev = getLootTableSeed();
|
||||
+ setLootTable(lootTableName, seed);
|
||||
+ return prev;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Clears the associated Loot Table to this object
|
||||
+ */
|
||||
+ void clearLootTable();
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableBlockInventory.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package com.destroystokyo.paper.loottable;
|
||||
+
|
||||
+import org.bukkit.block.Block;
|
||||
+
|
||||
+public interface LootableBlockInventory extends LootableInventory {
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the block that is lootable
|
||||
+ * @return The Block
|
||||
+ */
|
||||
+ Block getBlock();
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableEntityInventory.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package com.destroystokyo.paper.loottable;
|
||||
+
|
||||
+import org.bukkit.entity.Entity;
|
||||
+
|
||||
+public interface LootableEntityInventory extends LootableInventory {
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the entity that is lootable
|
||||
+ * @return The Entity
|
||||
+ */
|
||||
+ Entity getEntity();
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java b/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableInventory.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package com.destroystokyo.paper.loottable;
|
||||
+
|
||||
+import org.bukkit.entity.Player;
|
||||
+
|
||||
+import java.util.UUID;
|
||||
+
|
||||
+/**
|
||||
+ * Represents an Inventory that contains a Loot Table associated to it that will
|
||||
+ * automatically fill on first open.
|
||||
+ *
|
||||
+ * A new feature and API is provided to support automatically refreshing the contents
|
||||
+ * of the inventory based on that Loot Table after a configurable amount of time has passed.
|
||||
+ *
|
||||
+ * The behavior of how the Inventory is filled based on the loot table may vary based
|
||||
+ * on Minecraft versions and the Loot Table feature.
|
||||
+ */
|
||||
+public interface LootableInventory extends Lootable {
|
||||
+
|
||||
+ /**
|
||||
+ * Server owners have to enable whether or not an object in a world should refill
|
||||
+ *
|
||||
+ * @return If the world this inventory is currently in has Replenishable Lootables enabled
|
||||
+ */
|
||||
+ boolean isRefillEnabled();
|
||||
+
|
||||
+ /**
|
||||
+ * Whether or not this object has ever been filled
|
||||
+ * @return Has ever been filled
|
||||
+ */
|
||||
+ boolean hasBeenFilled();
|
||||
+
|
||||
+ /**
|
||||
+ * Has this player ever looted this block
|
||||
+ * @param player The player to check
|
||||
+ * @return Whether or not this player has looted this block
|
||||
+ */
|
||||
+ default boolean hasPlayerLooted(Player player) {
|
||||
+ return hasPlayerLooted(player.getUniqueId());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Has this player ever looted this block
|
||||
+ * @param player The player to check
|
||||
+ * @return Whether or not this player has looted this block
|
||||
+ */
|
||||
+ boolean hasPlayerLooted(UUID player);
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the timestamp, in milliseconds, of when the player last looted this object
|
||||
+ *
|
||||
+ * @param player The player to check
|
||||
+ * @return Timestamp last looted, or null if player has not looted this object
|
||||
+ */
|
||||
+ default Long getLastLooted(Player player) {
|
||||
+ return getLastLooted(player.getUniqueId());
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the timestamp, in milliseconds, of when the player last looted this object
|
||||
+ *
|
||||
+ * @param player The player to check
|
||||
+ * @return Timestamp last looted, or null if player has not looted this object
|
||||
+ */
|
||||
+ Long getLastLooted(UUID player);
|
||||
+
|
||||
+ /**
|
||||
+ * Change the state of whether or not a player has looted this block
|
||||
+ * @param player The player to change state for
|
||||
+ * @param looted true to add player to looted list, false to remove
|
||||
+ * @return The previous state of whether the player had looted this or not
|
||||
+ */
|
||||
+ default boolean setHasPlayerLooted(Player player, boolean looted) {
|
||||
+ return setHasPlayerLooted(player.getUniqueId(), looted);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Change the state of whether or not a player has looted this block
|
||||
+ * @param player The player to change state for
|
||||
+ * @param looted true to add player to looted list, false to remove
|
||||
+ * @return The previous state of whether the player had looted this or not
|
||||
+ */
|
||||
+ boolean setHasPlayerLooted(UUID player, boolean looted);
|
||||
+
|
||||
+ /**
|
||||
+ * Returns Whether or not this object has been filled and now has a pending refill
|
||||
+ * @return Has pending refill
|
||||
+ */
|
||||
+ boolean hasPendingRefill();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the timestamp in milliseconds that the Lootable object was last refilled
|
||||
+ *
|
||||
+ * @return -1 if it was never refilled, or timestamp in milliseconds
|
||||
+ */
|
||||
+ long getLastFilled();
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the timestamp in milliseconds that the Lootable object will refill
|
||||
+ *
|
||||
+ * @return -1 if it is not scheduled for refill, or timestamp in milliseconds
|
||||
+ */
|
||||
+ long getNextRefill();
|
||||
+
|
||||
+ /**
|
||||
+ * Sets the timestamp in milliseconds of the next refill for this object
|
||||
+ *
|
||||
+ * @param refillAt timestamp in milliseconds. -1 to clear next refill
|
||||
+ * @return The previous scheduled time to refill, or -1 if was not scheduled
|
||||
+ */
|
||||
+ long setNextRefill(long refillAt);
|
||||
+}
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java b/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/LootableInventoryReplenishEvent.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package com.destroystokyo.paper.loottable;
|
||||
+
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.Cancellable;
|
||||
+import org.bukkit.event.HandlerList;
|
||||
+import org.bukkit.event.player.PlayerEvent;
|
||||
+
|
||||
+public class LootableInventoryReplenishEvent extends PlayerEvent implements Cancellable {
|
||||
+ private final LootableInventory inventory;
|
||||
+
|
||||
+ public LootableInventoryReplenishEvent(Player player, LootableInventory inventory) {
|
||||
+ super(player);
|
||||
+ this.inventory = inventory;
|
||||
+ }
|
||||
+
|
||||
+ public LootableInventory getInventory() {
|
||||
+ return inventory;
|
||||
+ }
|
||||
+
|
||||
+ private static final HandlerList handlers = new HandlerList();
|
||||
+
|
||||
+ public HandlerList getHandlers() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ public static HandlerList getHandlerList() {
|
||||
+ return handlers;
|
||||
+ }
|
||||
+
|
||||
+ private boolean cancelled = false;
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCancelled() {
|
||||
+ return cancelled;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCancelled(boolean cancel) {
|
||||
+ cancelled = cancel;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/block/Chest.java b/src/main/java/org/bukkit/block/Chest.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/block/Chest.java
|
||||
+++ b/src/main/java/org/bukkit/block/Chest.java
|
||||
@@ -0,0 +0,0 @@
|
||||
package org.bukkit.block;
|
||||
|
||||
+import com.destroystokyo.paper.loottable.LootableInventory; // Paper
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
|
||||
/**
|
||||
* Represents a chest.
|
||||
*/
|
||||
-public interface Chest extends BlockState, InventoryHolder {
|
||||
+public interface Chest extends BlockState, InventoryHolder, LootableInventory { // Paper
|
||||
|
||||
/**
|
||||
* Returns the chest's inventory. If this is a double chest, it returns
|
||||
diff --git a/src/main/java/org/bukkit/block/Dispenser.java b/src/main/java/org/bukkit/block/Dispenser.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/block/Dispenser.java
|
||||
+++ b/src/main/java/org/bukkit/block/Dispenser.java
|
||||
@@ -0,0 +0,0 @@
|
||||
package org.bukkit.block;
|
||||
|
||||
+import com.destroystokyo.paper.loottable.LootableInventory; // Paper
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.projectiles.BlockProjectileSource;
|
||||
|
||||
/**
|
||||
* Represents a dispenser.
|
||||
*/
|
||||
-public interface Dispenser extends BlockState, InventoryHolder {
|
||||
+public interface Dispenser extends BlockState, InventoryHolder, LootableInventory { // Paper
|
||||
|
||||
/**
|
||||
* Gets the BlockProjectileSource object for this dispenser.
|
||||
diff --git a/src/main/java/org/bukkit/block/Hopper.java b/src/main/java/org/bukkit/block/Hopper.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/block/Hopper.java
|
||||
+++ b/src/main/java/org/bukkit/block/Hopper.java
|
||||
@@ -0,0 +0,0 @@
|
||||
package org.bukkit.block;
|
||||
|
||||
+import com.destroystokyo.paper.loottable.LootableInventory; // Paper
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
|
||||
/**
|
||||
* Represents a hopper.
|
||||
*/
|
||||
-public interface Hopper extends BlockState, InventoryHolder {
|
||||
+public interface Hopper extends BlockState, InventoryHolder, LootableInventory { // Paper
|
||||
|
||||
}
|
||||
--
|
|
@ -0,0 +1,699 @@
|
|||
From 0000000000000000000000000000000000000000 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootable.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableBlockInventory.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableEntityInventory.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventory.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/loottable/CraftLootableInventoryData.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityMinecartContainer.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityMinecartContainer.java
|
||||
@@ -0,0 +0,0 @@ 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>();
|
||||
@@ -0,0 +0,0 @@ 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) {
|
||||
@@ -0,0 +0,0 @@ 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");
|
||||
@@ -0,0 +0,0 @@ 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) {
|
||||
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/TileEntityLootable.java
|
||||
+++ b/src/main/java/net/minecraft/server/TileEntityLootable.java
|
||||
@@ -0,0 +0,0 @@
|
||||
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");
|
||||
@@ -0,0 +0,0 @@ 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) {
|
||||
@@ -0,0 +0,0 @@ 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) {
|
||||
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
|
||||
@@ -0,0 +0,0 @@
|
||||
package org.bukkit.craftbukkit.block;
|
||||
|
||||
+import com.destroystokyo.paper.loottable.CraftLootableBlockInventory; // Paper
|
||||
import net.minecraft.server.BlockPosition;
|
||||
import net.minecraft.server.TileEntityChest;
|
||||
|
||||
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftDispenser.java
|
||||
@@ -0,0 +0,0 @@
|
||||
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;
|
||||
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftHopper.java
|
||||
@@ -0,0 +0,0 @@
|
||||
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;
|
||||
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartChest.java
|
||||
@@ -0,0 +0,0 @@
|
||||
package org.bukkit.craftbukkit.entity;
|
||||
|
||||
+import com.destroystokyo.paper.loottable.CraftLootableEntityInventory; // Paper
|
||||
import net.minecraft.server.EntityMinecartChest;
|
||||
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartHopper.java
|
||||
@@ -0,0 +0,0 @@
|
||||
package org.bukkit.craftbukkit.entity;
|
||||
|
||||
+import com.destroystokyo.paper.loottable.CraftLootableEntityInventory; // Paper
|
||||
import net.minecraft.server.EntityMinecartHopper;
|
||||
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
@@ -0,0 +0,0 @@ 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) {
|
||||
--
|
|
@ -130,4 +130,44 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ return (modX == 0 || modX == 15 || modZ == 0 || modZ == 15);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/NBTTagCompound.java b/src/main/java/net/minecraft/server/NBTTagCompound.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/NBTTagCompound.java
|
||||
+++ b/src/main/java/net/minecraft/server/NBTTagCompound.java
|
||||
@@ -0,0 +0,0 @@ import java.util.concurrent.Callable;
|
||||
|
||||
public class NBTTagCompound extends NBTBase {
|
||||
|
||||
- private Map<String, NBTBase> map = Maps.newHashMap();
|
||||
+ public Map<String, NBTBase> map = Maps.newHashMap(); // Paper
|
||||
|
||||
public NBTTagCompound() {}
|
||||
|
||||
@@ -0,0 +0,0 @@ public class NBTTagCompound extends NBTBase {
|
||||
this.map.put(s, new NBTTagLong(i));
|
||||
}
|
||||
|
||||
+ public void setUUID(String prefix, UUID uuid) { a(prefix, uuid); } // Paper // OBFHELPER
|
||||
public void a(String s, UUID uuid) {
|
||||
this.setLong(s + "Most", uuid.getMostSignificantBits());
|
||||
this.setLong(s + "Least", uuid.getLeastSignificantBits());
|
||||
}
|
||||
|
||||
+ public UUID getUUID(String prefix) { return a(prefix); } // Paper // OBFHELPER
|
||||
public UUID a(String s) {
|
||||
return new UUID(this.getLong(s + "Most"), this.getLong(s + "Least"));
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/NBTTagList.java b/src/main/java/net/minecraft/server/NBTTagList.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/NBTTagList.java
|
||||
+++ b/src/main/java/net/minecraft/server/NBTTagList.java
|
||||
@@ -0,0 +0,0 @@ import org.apache.logging.log4j.Logger;
|
||||
public class NBTTagList extends NBTBase {
|
||||
|
||||
private static final Logger b = LogManager.getLogger();
|
||||
- private List<NBTBase> list = Lists.newArrayList();
|
||||
+ public List<NBTBase> list = Lists.newArrayList(); // Paper
|
||||
private byte type = 0;
|
||||
|
||||
public NBTTagList() {}
|
||||
--
|
|
@ -22,7 +22,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+import java.util.HashMap;
|
||||
+import java.util.List;
|
||||
+import java.util.Map;
|
||||
+import java.util.concurrent.TimeUnit;
|
||||
+import java.util.logging.Level;
|
||||
+import java.util.regex.Pattern;
|
||||
+
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import org.bukkit.Bukkit;
|
||||
|
@ -98,6 +100,46 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static final Pattern SPACE = Pattern.compile(" ");
|
||||
+ private static final Pattern NOT_NUMERIC = Pattern.compile("[^-\\d.]");
|
||||
+ public static int getSeconds(String str) {
|
||||
+ str = SPACE.matcher(str).replaceAll("");
|
||||
+ final char unit = str.charAt(str.length() - 1);
|
||||
+ str = NOT_NUMERIC.matcher(str).replaceAll("");
|
||||
+ double num;
|
||||
+ try {
|
||||
+ num = Double.parseDouble(str);
|
||||
+ } catch (Exception e) {
|
||||
+ num = 0D;
|
||||
+ }
|
||||
+ switch (unit) {
|
||||
+ case 'd': num *= (double) 60*60*24; break;
|
||||
+ case 'h': num *= (double) 60*60; break;
|
||||
+ case 'm': num *= (double) 60; break;
|
||||
+ default: case 's': break;
|
||||
+ }
|
||||
+ return (int) num;
|
||||
+ }
|
||||
+
|
||||
+ protected static String timeSummary(int seconds) {
|
||||
+ String time = "";
|
||||
+
|
||||
+ if (seconds > 60 * 60 * 24) {
|
||||
+ time += TimeUnit.SECONDS.toDays(seconds) + "d";
|
||||
+ seconds %= 60 * 60 * 24;
|
||||
+ }
|
||||
+
|
||||
+ if (seconds > 60 * 60) {
|
||||
+ time += TimeUnit.SECONDS.toHours(seconds) + "h";
|
||||
+ seconds %= 60 * 60;
|
||||
+ }
|
||||
+
|
||||
+ if (seconds > 0) {
|
||||
+ time += TimeUnit.SECONDS.toMinutes(seconds) + "m";
|
||||
+ }
|
||||
+ return time;
|
||||
+ }
|
||||
+
|
||||
+ private static void set(String path, Object val) {
|
||||
+ config.set(path, val);
|
||||
+ }
|
||||
|
|
|
@ -218,12 +218,9 @@ diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/j
|
|||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
@@ -0,0 +0,0 @@ import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
+import java.util.concurrent.TimeUnit;
|
||||
@@ -0,0 +0,0 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
+import com.google.common.collect.Lists;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
@ -259,19 +256,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
+ " - Verbose: " + verboseTimings +
|
||||
+ " - Interval: " + timeSummary(Timings.getHistoryInterval() / 20) +
|
||||
+ " - Length: " + timeSummary(Timings.getHistoryLength() / 20));
|
||||
+ }
|
||||
+
|
||||
+ protected static String timeSummary(int seconds) {
|
||||
+ String time = "";
|
||||
+ if (seconds > 60 * 60) {
|
||||
+ time += TimeUnit.SECONDS.toHours(seconds) + "h";
|
||||
+ seconds /= 60;
|
||||
+ }
|
||||
+
|
||||
+ if (seconds > 0) {
|
||||
+ time += TimeUnit.SECONDS.toMinutes(seconds) + "m";
|
||||
+ }
|
||||
+ return time;
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/Block.java b/src/main/java/net/minecraft/server/Block.java
|
||||
|
|
|
@ -9,8 +9,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
|||
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
@@ -0,0 +0,0 @@ public class PaperConfig {
|
||||
}
|
||||
return time;
|
||||
" - Interval: " + timeSummary(Timings.getHistoryInterval() / 20) +
|
||||
" - Length: " + timeSummary(Timings.getHistoryLength() / 20));
|
||||
}
|
||||
+
|
||||
+ public static boolean useInteractLimiter;
|
||||
|
|
|
@ -56,6 +56,8 @@ import EntitySquid
|
|||
import EntityWaterAnimal
|
||||
import FileIOThread
|
||||
import ItemBlock
|
||||
import NBTTagCompound
|
||||
import NBTTagList
|
||||
import PacketPlayInResourcePackStatus
|
||||
import PacketPlayInUseEntity
|
||||
import PacketPlayOutPlayerListHeaderFooter
|
||||
|
@ -68,6 +70,7 @@ import PathfinderWater
|
|||
import PersistentVillage
|
||||
import RemoteControlListener
|
||||
import TileEntityEnderChest
|
||||
import TileEntityLootable
|
||||
import WorldProvider
|
||||
|
||||
cd "$workdir/Spigot/Spigot-Server/"
|
||||
|
|
Loading…
Reference in a new issue