From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Mark Vainomaa 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/com/destroystokyo/paper/Namespaced.java b/src/main/java/com/destroystokyo/paper/Namespaced.java new file mode 100644 index 0000000000000000000000000000000000000000..cd1a34b82870684e09e18c47169bd472ecbbb91f --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/Namespaced.java @@ -0,0 +1,40 @@ +package com.destroystokyo.paper; + +import org.jetbrains.annotations.NotNull; + +/** + * Represents a namespaced resource, see {@link org.bukkit.NamespacedKey} for single elements + * or {@link com.destroystokyo.paper.NamespacedTag} for a collection of elements + * + * Namespaces may only contain lowercase alphanumeric characters, periods, + * underscores, and hyphens. + *

+ * Keys may only contain lowercase alphanumeric characters, periods, + * underscores, hyphens, and forward slashes. + *

+ * You should not be implementing this interface yourself, use {@link org.bukkit.NamespacedKey} + * or {@link com.destroystokyo.paper.NamespacedTag} as needed instead. + */ +public interface Namespaced { + /** + * Gets the namespace this resource is a part of + *

+ * This is contractually obligated to only contain lowercase alphanumeric characters, + * periods, underscores, and hyphens. + * + * @return resource namespace + */ + @NotNull + String getNamespace(); + + /** + * Gets the key corresponding to this resource + *

+ * This is contractually obligated to only contain lowercase alphanumeric characters, + * periods, underscores, hyphens, and forward slashes. + * + * @return resource key + */ + @NotNull + String getKey(); +} diff --git a/src/main/java/com/destroystokyo/paper/NamespacedTag.java b/src/main/java/com/destroystokyo/paper/NamespacedTag.java new file mode 100644 index 0000000000000000000000000000000000000000..28f3fda950999a9c964a3608042ca60567ae1d6a --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/NamespacedTag.java @@ -0,0 +1,142 @@ +package com.destroystokyo.paper; + +import com.google.common.base.Preconditions; +import java.util.Locale; +import java.util.UUID; +import java.util.regex.Pattern; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; + +/** + * Represents a String based key pertaining to a tagged entry. Consists of two components - a namespace + * and a key. + *

+ * Namespaces may only contain lowercase alphanumeric characters, periods, + * underscores, and hyphens. + *

+ * Keys may only contain lowercase alphanumeric characters, periods, + * underscores, hyphens, and forward slashes. + * + */ +// Paper - entire class, based on org.bukkit.NamespacedKey +public final class NamespacedTag implements com.destroystokyo.paper.Namespaced { + + /** + * The namespace representing all inbuilt keys. + */ + public static final String MINECRAFT = "minecraft"; + /** + * The namespace representing all keys generated by Bukkit for backwards + * compatibility measures. + */ + public static final String BUKKIT = "bukkit"; + // + private static final Pattern VALID_NAMESPACE = Pattern.compile("[a-z0-9._-]+"); + private static final Pattern VALID_KEY = Pattern.compile("[a-z0-9/._-]+"); + // + private final String namespace; + private final String key; + + /** + * Create a key in a specific namespace. + * + * @param namespace String representing a grouping of keys + * @param key Name for this specific key + * @deprecated should never be used by plugins, for internal use only!! + */ + @Deprecated + public NamespacedTag(@NotNull String namespace, @NotNull String key) { + Preconditions.checkArgument(namespace != null && VALID_NAMESPACE.matcher(namespace).matches(), "Invalid namespace. Must be [a-z0-9._-]: %s", namespace); + Preconditions.checkArgument(key != null && VALID_KEY.matcher(key).matches(), "Invalid key. Must be [a-z0-9/._-]: %s", key); + + this.namespace = namespace; + this.key = key; + + String string = toString(); + Preconditions.checkArgument(string.length() < 256, "NamespacedTag must be less than 256 characters", string); + } + + /** + * Create a key in the plugin's namespace. + *

+ * Namespaces may only contain lowercase alphanumeric characters, periods, + * underscores, and hyphens. + *

+ * Keys may only contain lowercase alphanumeric characters, periods, + * underscores, hyphens, and forward slashes. + * + * @param plugin the plugin to use for the namespace + * @param key the key to create + */ + public NamespacedTag(@NotNull Plugin plugin, @NotNull String key) { + Preconditions.checkArgument(plugin != null, "Plugin cannot be null"); + Preconditions.checkArgument(key != null, "Key cannot be null"); + + this.namespace = plugin.getName().toLowerCase(Locale.ROOT); + this.key = key.toLowerCase().toLowerCase(Locale.ROOT); + + // Check validity after normalization + Preconditions.checkArgument(VALID_NAMESPACE.matcher(this.namespace).matches(), "Invalid namespace. Must be [a-z0-9._-]: %s", this.namespace); + Preconditions.checkArgument(VALID_KEY.matcher(this.key).matches(), "Invalid key. Must be [a-z0-9/._-]: %s", this.key); + + String string = toString(); + Preconditions.checkArgument(string.length() < 256, "NamespacedTag must be less than 256 characters (%s)", string); + } + + @NotNull + public String getNamespace() { + return namespace; + } + + @NotNull + public String getKey() { + return key; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 47 * hash + this.namespace.hashCode(); + hash = 47 * hash + this.key.hashCode(); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final NamespacedTag other = (NamespacedTag) obj; + return this.namespace.equals(other.namespace) && this.key.equals(other.key); + } + + @Override + public String toString() { + return "#" + this.namespace + ":" + this.key; + } + + /** + * Return a new random key in the {@link #BUKKIT} namespace. + * + * @return new key + * @deprecated should never be used by plugins, for internal use only!! + */ + @Deprecated + public static NamespacedTag randomKey() { + return new NamespacedTag(BUKKIT, UUID.randomUUID().toString()); + } + + /** + * Get a key in the Minecraft namespace. + * + * @param key the key to use + * @return new key in the Minecraft namespace + */ + @NotNull + public static NamespacedTag minecraft(@NotNull String key) { + return new NamespacedTag(MINECRAFT, key); + } +} diff --git a/src/main/java/org/bukkit/NamespacedKey.java b/src/main/java/org/bukkit/NamespacedKey.java index c65f0d6569c130b4920a9e71ad24af6427f1f030..01bcb3a1bdb5accdf844d0178cec3d25746b3eaa 100644 --- a/src/main/java/org/bukkit/NamespacedKey.java +++ b/src/main/java/org/bukkit/NamespacedKey.java @@ -19,7 +19,7 @@ import org.jetbrains.annotations.Nullable; * underscores, hyphens, and forward slashes. * */ -public final class NamespacedKey implements net.kyori.adventure.key.Key { // Paper - implement Key +public final class NamespacedKey implements net.kyori.adventure.key.Key, com.destroystokyo.paper.Namespaced { // Paper - implement Key and Namespaced /** * The namespace representing all inbuilt keys. @@ -84,11 +84,13 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key { // Pap } @NotNull + @Override // Paper public String getNamespace() { return namespace; } @NotNull + @Override // Paper public String getKey() { return key; } diff --git a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java index a19635c38705e6221ae25d58e976e483e7ed17e4..71c7780424a986a95852b1ca15116096896500df 100644 --- a/src/main/java/org/bukkit/inventory/meta/ItemMeta.java +++ b/src/main/java/org/bukkit/inventory/meta/ItemMeta.java @@ -444,4 +444,87 @@ public interface ItemMeta extends Cloneable, ConfigurationSerializable, Persiste @SuppressWarnings("javadoc") @NotNull ItemMeta clone(); + + // 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 + * @deprecated Minecraft does not limit this to the material enum, Use {@link #getDestroyableKeys()} as a replacement + */ + @Deprecated + Set getCanDestroy(); + + /** + * Sets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE} + * + * @param canDestroy Set of materials + * @deprecated Minecraft does not limit this to the material enum, Use {@link #setDestroyableKeys(Collection)} as a replacement + */ + @Deprecated + void setCanDestroy(Set canDestroy); + + /** + * Gets set of materials where given item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} + * + * @return Set of materials + * @deprecated Minecraft does not limit this to the material enum, Use {@link #getPlaceableKeys()} as a replacement + */ + @Deprecated + Set getCanPlaceOn(); + + /** + * Sets set of materials where given item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} + * + * @param canPlaceOn Set of materials + * @deprecated Minecraft does not limit this to the material enum, Use {@link #setPlaceableKeys(Collection)} as a replacement + */ + @Deprecated + void setCanPlaceOn(Set canPlaceOn); + + /** + * Gets the collection of namespaced keys that the item can destroy in {@link org.bukkit.GameMode#ADVENTURE} + * + * @return Set of {@link com.destroystokyo.paper.Namespaced} + */ + @NotNull + Set getDestroyableKeys(); + + /** + * Sets the collection of namespaced keys that the item can destroy in {@link org.bukkit.GameMode#ADVENTURE} + * + * @param canDestroy Collection of {@link com.destroystokyo.paper.Namespaced} + */ + void setDestroyableKeys(@NotNull Collection canDestroy); + + /** + * Gets the collection of namespaced keys that the item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} + * + * @return Set of {@link com.destroystokyo.paper.Namespaced} + */ + @NotNull + Set getPlaceableKeys(); + + /** + * Sets the set of namespaced keys that the item can be placed on in {@link org.bukkit.GameMode#ADVENTURE} + * + * @param canPlaceOn Collection of {@link com.destroystokyo.paper.Namespaced} + */ + @NotNull + void setPlaceableKeys(@NotNull Collection canPlaceOn); + + /** + * Checks for the existence of any keys that the item can be placed on + * + * @return true if this item has placeable keys + */ + boolean hasPlaceableKeys(); + + /** + * Checks for the existence of any keys that the item can destroy + * + * @return true if this item has destroyable keys + */ + boolean hasDestroyableKeys(); + // Paper end }