From be9ef980b9aa272acf298a337da8157c6a620e95 Mon Sep 17 00:00:00 2001
From: md_5 <git@md-5.net>
Date: Wed, 19 Apr 2017 18:04:32 +1000
Subject: [PATCH] Implement cooldown API

---
 nms-patches/ItemCooldown.patch                | 26 +++++++++++++++++++
 nms-patches/PlayerInteractManager.patch       | 21 ++++++++-------
 .../craftbukkit/entity/CraftHumanEntity.java  | 24 +++++++++++++++++
 3 files changed, 62 insertions(+), 9 deletions(-)
 create mode 100644 nms-patches/ItemCooldown.patch

diff --git a/nms-patches/ItemCooldown.patch b/nms-patches/ItemCooldown.patch
new file mode 100644
index 0000000000..8925a837b7
--- /dev/null
+++ b/nms-patches/ItemCooldown.patch
@@ -0,0 +1,26 @@
+--- a/net/minecraft/server/ItemCooldown.java
++++ b/net/minecraft/server/ItemCooldown.java
+@@ -7,8 +7,8 @@
+ 
+ public class ItemCooldown {
+ 
+-    private final Map<Item, ItemCooldown.Info> a = Maps.newHashMap();
+-    private int b;
++    public final Map<Item, ItemCooldown.Info> a = Maps.newHashMap(); // PAIL: private->public
++    public int b; // PAIL: currentTick, private->public
+ 
+     public ItemCooldown() {}
+ 
+@@ -55,10 +55,10 @@
+ 
+     protected void c(Item item) {}
+ 
+-    class Info {
++    public class Info { // PAIL: private->public
+ 
+         final int a;
+-        final int b;
++        public final int b; // PAIL: endTick, private->public
+ 
+         private Info(int i, int j) {
+             this.a = i;
diff --git a/nms-patches/PlayerInteractManager.patch b/nms-patches/PlayerInteractManager.patch
index ba41f0f422..3db81a13c7 100644
--- a/nms-patches/PlayerInteractManager.patch
+++ b/nms-patches/PlayerInteractManager.patch
@@ -52,7 +52,7 @@
          if (this.isCreative()) {
              if (!this.world.douseFire((EntityHuman) null, blockposition, enumdirection)) {
                  this.breakBlock(blockposition);
-@@ -125,15 +146,49 @@
+@@ -125,14 +146,48 @@
                  }
              }
  
@@ -79,8 +79,8 @@
                  f = iblockdata.a((EntityHuman) this.player, this.player.world, blockposition);
 +                // Allow fire punching to be blocked
 +                this.world.douseFire((EntityHuman) null, blockposition, enumdirection);
-             }
- 
++            }
++
 +            if (event.useItemInHand() == Event.Result.DENY) {
 +                // If we 'insta destroyed' then the client needs to be informed.
 +                if (f > 1.0f) {
@@ -98,12 +98,11 @@
 +
 +            if (blockEvent.getInstaBreak()) {
 +                f = 2.0f;
-+            }
+             }
 +            // CraftBukkit end
-+
+ 
              if (iblockdata.getMaterial() != Material.AIR && f >= 1.0F) {
                  this.breakBlock(blockposition);
-             } else {
 @@ -150,6 +205,7 @@
  
      public void a(BlockPosition blockposition) {
@@ -224,7 +223,7 @@
                  return flag;
              }
          }
-@@ -280,63 +419,86 @@
+@@ -280,63 +419,90 @@
          }
      }
  
@@ -250,12 +249,16 @@
 -                if (itileinventory instanceof TileEntityChest && block instanceof BlockChest) {
 -                    itileinventory = ((BlockChest) block).c(world, blockposition);
 -                }
-+            if (itemstack.getItem() instanceof ItemBlock && !entityhuman.dk()) { // PAIL: creativeAndOp
-+                Block block1 = ((ItemBlock) itemstack.getItem()).getBlock();
++            if (entityhuman.di().a(itemstack.getItem())) {
++                cancelledBlock = true;
++            }
  
 -                if (itileinventory != null) {
 -                    entityhuman.openContainer(itileinventory);
 -                    return EnumInteractionResult.SUCCESS;
++            if (itemstack.getItem() instanceof ItemBlock && !entityhuman.dk()) { // PAIL: creativeAndOp
++                Block block1 = ((ItemBlock) itemstack.getItem()).getBlock();
++
 +                if (block1 instanceof BlockCommand || block1 instanceof BlockStructure) {
 +                    cancelledBlock = true;
                  }
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
index 0397756cd5..62aab50b3c 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
@@ -26,6 +26,7 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryView;
 import org.bukkit.craftbukkit.inventory.CraftItemStack;
 import org.bukkit.craftbukkit.inventory.CraftMerchant;
 import org.bukkit.craftbukkit.CraftServer;
+import org.bukkit.craftbukkit.util.CraftMagicNumbers;
 import org.bukkit.inventory.EntityEquipment;
 import org.bukkit.permissions.PermissibleBase;
 import org.bukkit.permissions.Permission;
@@ -416,4 +417,27 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
     public int getExpToLevel() {
         return getHandle().getExpToLevel();
     }
+
+    @Override
+    public boolean hasCooldown(Material material) {
+        Preconditions.checkArgument(material != null, "material");
+
+        return getHandle().di().a(CraftMagicNumbers.getItem(material)); // PAIL: getCooldownTracker
+    }
+
+    @Override
+    public int getCooldown(Material material) {
+        Preconditions.checkArgument(material != null, "material");
+
+        ItemCooldown.Info cooldown = getHandle().di().a.get(CraftMagicNumbers.getItem(material));
+        return (cooldown == null) ? 0 : Math.max(0, cooldown.b - getHandle().di().b);
+    }
+
+    @Override
+    public void setCooldown(Material material, int ticks) {
+        Preconditions.checkArgument(material != null, "material");
+        Preconditions.checkArgument(ticks >= 0, "Cannot have negative cooldown");
+
+        getHandle().di().a(CraftMagicNumbers.getItem(material), ticks);
+    }
 }