From d326b41a9110a347d378723aa4a9677e6c1c6115 Mon Sep 17 00:00:00 2001
From: Mark Vainomaa <mikroskeem@gmail.com>
Date: Sun, 23 Sep 2018 06:30:54 +0300
Subject: [PATCH] Create API for CanPlaceOn and CanDestroy NBT tags (#1015)

---
 ...CanPlaceOn-and-CanDestroy-NBT-values.patch |  45 ++++++
 ...e-attack-cooldown-methods-for-Player.patch |   2 +-
 Spigot-Server-Patches/Fix-1420.patch          |   2 +-
 ...-for-CanPlaceOn-and-CanDestroy-NBT-v.patch | 143 ++++++++++++++++++
 Spigot-Server-Patches/Spigot-PR-493.patch     |   2 +-
 5 files changed, 191 insertions(+), 3 deletions(-)
 create mode 100644 Spigot-API-Patches/Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch
 create mode 100644 Spigot-Server-Patches/Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch

diff --git a/Spigot-API-Patches/Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch b/Spigot-API-Patches/Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch
new file mode 100644
index 0000000000..f5dc3d9ae4
--- /dev/null
+++ b/Spigot-API-Patches/Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch
@@ -0,0 +1,45 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Mark Vainomaa <mikroskeem@mikroskeem.eu>
+Date: Wed, 12 Sep 2018 18:53:35 +0300
+Subject: [PATCH] Add an API for CanPlaceOn and CanDestroy NBT values
+
+
+diff --git a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java
+index 8d8f09879..97fa7807b 100644
+--- a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java
++++ b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java
+@@ -0,0 +0,0 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable {
+ 
+     Spigot spigot();
+     // Spigot end
++    // Paper start - Add an API for CanPlaceOn and CanDestroy NBT values
++    /**
++     * Gets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE}
++     *
++     * @return Set of materials
++     */
++    Set<org.bukkit.Material> getCanDestroy();
++
++    /**
++     * Sets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE}
++     *
++     * @param canDestroy Set of materials
++     */
++    void setCanDestroy(Set<org.bukkit.Material> canDestroy);
++
++    /**
++     * Gets set of materials where given item can be placed on in {@link org.bukkit.GameMode#ADVENTURE}
++     *
++     * @return Set of materials
++     */
++    Set<org.bukkit.Material> getCanPlaceOn();
++
++    /**
++     * Sets set of materials where given item can be placed on in {@link org.bukkit.GameMode#ADVENTURE}
++     *
++     * @param canPlaceOn Set of materials
++     */
++    void setCanPlaceOn(Set<org.bukkit.Material> canPlaceOn);
++    // Paper end
+ }
+--
\ No newline at end of file
diff --git a/Spigot-API-Patches/Expose-attack-cooldown-methods-for-Player.patch b/Spigot-API-Patches/Expose-attack-cooldown-methods-for-Player.patch
index 33c3285d72..a6c92bbfad 100644
--- a/Spigot-API-Patches/Expose-attack-cooldown-methods-for-Player.patch
+++ b/Spigot-API-Patches/Expose-attack-cooldown-methods-for-Player.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Expose attack cooldown methods for Player
 
 
 diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
-index 6da68835..ae2b9752 100644
+index 6da68835d..ae2b9752b 100644
 --- a/src/main/java/org/bukkit/entity/Player.java
 +++ b/src/main/java/org/bukkit/entity/Player.java
 @@ -0,0 +0,0 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline
diff --git a/Spigot-Server-Patches/Fix-1420.patch b/Spigot-Server-Patches/Fix-1420.patch
index 94f7eae253..9ea2ebd072 100644
--- a/Spigot-Server-Patches/Fix-1420.patch
+++ b/Spigot-Server-Patches/Fix-1420.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Fix #1420
 
 
 diff --git a/src/main/java/net/minecraft/server/EntityArrow.java b/src/main/java/net/minecraft/server/EntityArrow.java
-index 187f02d4e4..fcb1cb36af 100644
+index a82dc0a94e..529629a867 100644
 --- a/src/main/java/net/minecraft/server/EntityArrow.java
 +++ b/src/main/java/net/minecraft/server/EntityArrow.java
 @@ -0,0 +0,0 @@ public abstract class EntityArrow extends Entity implements IProjectile {
diff --git a/Spigot-Server-Patches/Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch b/Spigot-Server-Patches/Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch
new file mode 100644
index 0000000000..ed1c70bedf
--- /dev/null
+++ b/Spigot-Server-Patches/Implement-an-API-for-CanPlaceOn-and-CanDestroy-NBT-v.patch
@@ -0,0 +1,143 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Mark Vainomaa <mikroskeem@mikroskeem.eu>
+Date: Wed, 12 Sep 2018 18:53:55 +0300
+Subject: [PATCH] Implement an API for CanPlaceOn and CanDestroy NBT values
+
+
+diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
+index b90a02ef6f..c9d4d45564 100644
+--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
+@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable {
+     static final ItemMetaKey UNBREAKABLE = new ItemMetaKey("Unbreakable");
+     @Specific(Specific.To.NBT)
+     static final ItemMetaKey DAMAGE = new ItemMetaKey("Damage");
++    // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values
++    @Specific(Specific.To.NBT)
++    static final ItemMetaKey CAN_DESTROY = new ItemMetaKey("CanDestroy");
++    @Specific(Specific.To.NBT)
++    static final ItemMetaKey CAN_PLACE_ON = new ItemMetaKey("CanPlaceOn");
++    // Paper end
+ 
+     private IChatBaseComponent displayName;
+     private IChatBaseComponent locName;
+@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable {
+     private int hideFlag;
+     private boolean unbreakable;
+     private int damage;
++    // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values
++    private Set<Material> canPlaceOn = Sets.newHashSet();
++    private Set<Material> canDestroy = Sets.newHashSet();
++    // Paper end
+ 
+     private static final Set<String> HANDLED_TAGS = Sets.newHashSet();
+ 
+@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable {
+         this.hideFlag = meta.hideFlag;
+         this.unbreakable = meta.unbreakable;
+         this.damage = meta.damage;
++        // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values
++        this.canDestroy = new java.util.HashSet<>(meta.canDestroy);
++        this.canPlaceOn = new java.util.HashSet<>(meta.canPlaceOn);
++        // Paper end
+         this.unhandledTags.putAll(meta.unhandledTags);
+ 
+         this.internalTag = meta.internalTag;
+@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable {
+         if (tag.hasKey(DAMAGE.NBT)) {
+             damage = tag.getInt(DAMAGE.NBT);
+         }
++        // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values
++        if (tag.hasKey(CAN_DESTROY.NBT)) {
++            NBTTagList list = tag.getList(CAN_DESTROY.NBT, CraftMagicNumbers.NBT.TAG_STRING);
++            for (int i = 0; i < list.size(); i++) {
++                Material material = Material.matchMaterial(list.getString(i), false);
++                this.canDestroy.add(material);
++            }
++        }
++
++        if (tag.hasKey(CAN_PLACE_ON.NBT)) {
++            NBTTagList list = tag.getList(CAN_PLACE_ON.NBT, CraftMagicNumbers.NBT.TAG_STRING);
++            for (int i = 0; i < list.size(); i++) {
++                Material material = Material.matchMaterial(list.getString(i), false);
++                this.canPlaceOn.add(material);
++            }
++        }
++        // Paper end
+ 
+         Set<String> keys = tag.getKeys();
+         for (String key : keys) {
+@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable {
+         if (hasDamage()) {
+             itemTag.setInt(DAMAGE.NBT, damage);
+         }
++        // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values
++        if (!this.canPlaceOn.isEmpty()) {
++            List<String> items = this.canPlaceOn.stream()
++                .map(Material::getKey)
++                .map(org.bukkit.NamespacedKey::toString)
++                .collect(java.util.stream.Collectors.toList());
++
++            itemTag.set(CAN_PLACE_ON.NBT, createStringList(items));
++        }
++
++        if (!this.canDestroy.isEmpty()) {
++            List<String> items = this.canDestroy.stream()
++                .map(Material::getKey)
++                .map(org.bukkit.NamespacedKey::toString)
++                .collect(java.util.stream.Collectors.toList());
++
++            itemTag.set(CAN_DESTROY.NBT, createStringList(items));
++        }
++        // Paper end
+ 
+         for (Map.Entry<String, NBTBase> e : unhandledTags.entrySet()) {
+             itemTag.set(e.getKey(), e.getValue());
+@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable {
+                         CraftMetaArmorStand.NO_BASE_PLATE.NBT,
+                         CraftMetaArmorStand.SHOW_ARMS.NBT,
+                         CraftMetaArmorStand.SMALL.NBT,
+-                        CraftMetaArmorStand.MARKER.NBT
++                        CraftMetaArmorStand.MARKER.NBT,
++                        CAN_DESTROY.NBT,
++                        CAN_PLACE_ON.NBT
+                         // Paper end
+                 ));
+             }
+@@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable {
+         return spigot;
+     }
+     // Spigot end
++    // Paper start - Implement an API for CanPlaceOn and CanDestroy NBT values
++    @Override
++    public Set<Material> getCanDestroy() {
++        return new java.util.HashSet<>(canDestroy);
++    }
++
++    @Override
++    @SuppressWarnings("deprecation")
++    public void setCanDestroy(Set<Material> canDestroy) {
++        if (canDestroy.stream().anyMatch(Material::isLegacy)) {
++            throw new IllegalArgumentException("canDestroy set must not contain any legacy materials!");
++        }
++        this.canDestroy.clear();
++        this.canDestroy.addAll(canDestroy);
++    }
++
++    @Override
++    public Set<Material> getCanPlaceOn() {
++        return new java.util.HashSet<>(canPlaceOn);
++    }
++
++    @Override
++    @SuppressWarnings("deprecation")
++    public void setCanPlaceOn(Set<Material> canPlaceOn) {
++        if (canPlaceOn.stream().anyMatch(Material::isLegacy)) {
++            throw new IllegalArgumentException("canPlaceOn set must not contain any legacy materials!");
++        }
++        this.canPlaceOn.clear();
++        this.canPlaceOn.addAll(canPlaceOn);
++    }
++    // Paper end
+ }
+--
\ No newline at end of file
diff --git a/Spigot-Server-Patches/Spigot-PR-493.patch b/Spigot-Server-Patches/Spigot-PR-493.patch
index b815b3886d..403c6cd9a3 100644
--- a/Spigot-Server-Patches/Spigot-PR-493.patch
+++ b/Spigot-Server-Patches/Spigot-PR-493.patch
@@ -5,7 +5,7 @@ Subject: [PATCH] Spigot PR 493
 
 
 diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
-index b90a02ef6f..55afe8382c 100644
+index c9d4d45564..d928119254 100644
 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
 +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
 @@ -0,0 +0,0 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable {