From 3cb3616012d90ba4522014d2447b345864eb1b30 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Sun, 11 Aug 2024 13:51:37 -0700 Subject: [PATCH] Re-add patches for can-place/can-destroy API (#11238) * Re-add patches for can-place/can-destroy API This API is all deprecated for removal and has to be replaced as the structure of it has too radically changed * update patches * add link to MaterialRerouting * Deprecation --------- Co-authored-by: Bjarne Koll --- ...CanPlaceOn-and-CanDestroy-NBT-values.patch | 332 ++++++++++++++++++ ...CanPlaceOn-and-CanDestroy-NBT-values.patch | 155 ++++++++ patches/server/Adopt-MaterialRerouting.patch | 4 +- 3 files changed, 489 insertions(+), 2 deletions(-) create mode 100644 patches/api/Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch create mode 100644 patches/server/Add-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch diff --git a/patches/api/Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch b/patches/api/Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch new file mode 100644 index 0000000000..d91b7640a5 --- /dev/null +++ b/patches/api/Add-an-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch @@ -0,0 +1,332 @@ +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..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/Namespaced.java +@@ -0,0 +0,0 @@ ++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. ++ */ ++@Deprecated(forRemoval = true, since = "1.20.6") ++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..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/com/destroystokyo/paper/NamespacedTag.java +@@ -0,0 +0,0 @@ ++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 ++@Deprecated(forRemoval = true, since = "1.20.6") ++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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/NamespacedKey.java ++++ b/src/main/java/org/bukkit/NamespacedKey.java +@@ -0,0 +0,0 @@ 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. +@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 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, Persiste + @SuppressWarnings("javadoc") + @NotNull + ItemMeta clone(); ++ ++ // Paper start - Add an API for can-place-on/can-break adventure mode predicates ++ /** ++ * Gets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE} ++ * ++ * @return Set of materials ++ * @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. ++ */ ++ @Deprecated(forRemoval = true, since = "1.14") ++ Set getCanDestroy(); ++ ++ /** ++ * Sets set of materials what given item can destroy in {@link org.bukkit.GameMode#ADVENTURE} ++ * ++ * @param canDestroy Set of materials ++ * @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. ++ */ ++ @Deprecated(forRemoval = true, since = "1.14") ++ 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 this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. ++ */ ++ @Deprecated(forRemoval = true, since = "1.14") ++ 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 this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. ++ */ ++ @Deprecated(forRemoval = true, since = "1.14") ++ 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} ++ * @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.6") ++ @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} ++ * @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.6") ++ 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} ++ * @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. ++ */ ++ @NotNull ++ @Deprecated(forRemoval = true, since = "1.20.6") ++ 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} ++ * @deprecated this API is unsupported and will be replaced, its usage may result in data loss related to place/destroy predicates. ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.6") ++ 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 ++ * @deprecated this API is unsupported and will be replaced ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.6") ++ boolean hasPlaceableKeys(); ++ ++ /** ++ * Checks for the existence of any keys that the item can destroy ++ * ++ * @return true if this item has destroyable keys ++ * @deprecated this API is unsupported and will be replaced ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.6") ++ boolean hasDestroyableKeys(); ++ // Paper end - Add an API for can-place-on/can-break adventure mode predicates + } diff --git a/patches/server/Add-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch b/patches/server/Add-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch new file mode 100644 index 0000000000..601940d7a9 --- /dev/null +++ b/patches/server/Add-API-for-CanPlaceOn-and-CanDestroy-NBT-values.patch @@ -0,0 +1,155 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 12 Sep 2018 18:53:55 +0300 +Subject: [PATCH] Add 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 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, BlockDataMeta { + } + // Paper end + ++ // Paper start - Add an API for can-place-on/can-break adventure mode predicates ++ @Override ++ public Set getCanDestroy() { ++ return !this.hasDestroyableKeys() ? Collections.emptySet() : convertToLegacyMaterial(this.canBreakPredicates); ++ } ++ ++ @Override ++ public void setCanDestroy(final Set canDestroy) { ++ Preconditions.checkArgument(canDestroy != null, "Cannot replace with null set!"); ++ this.canBreakPredicates = convertFromLegacyMaterial(canDestroy); ++ } ++ ++ @Override ++ public Set getCanPlaceOn() { ++ return !this.hasPlaceableKeys() ? Collections.emptySet() : convertToLegacyMaterial(this.canPlaceOnPredicates); ++ } ++ ++ @Override ++ public void setCanPlaceOn(final Set canPlaceOn) { ++ Preconditions.checkArgument(canPlaceOn != null, "Cannot replace with null set!"); ++ this.canPlaceOnPredicates = convertFromLegacyMaterial(canPlaceOn); ++ } ++ ++ private static List convertFromLegacyMaterial(final Collection materials) { ++ return materials.stream().map(m -> { ++ return net.minecraft.advancements.critereon.BlockPredicate.Builder.block().of(CraftBlockType.bukkitToMinecraft(m)).build(); ++ }).toList(); ++ } ++ ++ private static Set convertToLegacyMaterial(final List predicates) { ++ return predicates.stream() ++ .flatMap(p -> p.blocks().map(net.minecraft.core.HolderSet::stream).orElse(java.util.stream.Stream.empty())) ++ .map(holder -> CraftBlockType.minecraftToBukkit(holder.value())) ++ .collect(java.util.stream.Collectors.toSet()); ++ } ++ ++ @Override ++ public Set getDestroyableKeys() { ++ return !this.hasDestroyableKeys() ? Collections.emptySet() : convertToLegacyNamespaced(this.canBreakPredicates); ++ } ++ ++ @Override ++ public void setDestroyableKeys(final Collection canDestroy) { ++ Preconditions.checkArgument(canDestroy != null, "Cannot replace with null collection!"); ++ Preconditions.checkArgument(ofAcceptableType(canDestroy), "Can only use NamespacedKey or NamespacedTag objects!"); ++ this.canBreakPredicates = convertFromLegacyNamespaced(canDestroy); ++ } ++ ++ @Override ++ public Set getPlaceableKeys() { ++ return !this.hasPlaceableKeys() ? Collections.emptySet() : convertToLegacyNamespaced(this.canPlaceOnPredicates); ++ } ++ ++ @Override ++ public void setPlaceableKeys(final Collection canPlaceOn) { ++ Preconditions.checkArgument(canPlaceOn != null, "Cannot replace with null collection!"); ++ Preconditions.checkArgument(ofAcceptableType(canPlaceOn), "Can only use NamespacedKey or NamespacedTag objects!"); ++ this.canPlaceOnPredicates = convertFromLegacyNamespaced(canPlaceOn); ++ } ++ ++ private static List convertFromLegacyNamespaced(final Collection namespaceds) { ++ final List predicates = new ArrayList<>(); ++ for (final com.destroystokyo.paper.Namespaced namespaced : namespaceds) { ++ if (namespaced instanceof final org.bukkit.NamespacedKey key) { ++ predicates.add(net.minecraft.advancements.critereon.BlockPredicate.Builder.block().of(CraftBlockType.bukkitToMinecraft(Objects.requireNonNull(org.bukkit.Registry.MATERIAL.get(key)))).build()); ++ } else if (namespaced instanceof final com.destroystokyo.paper.NamespacedTag tag) { ++ predicates.add(net.minecraft.advancements.critereon.BlockPredicate.Builder.block().of(net.minecraft.tags.TagKey.create(Registries.BLOCK, ResourceLocation.fromNamespaceAndPath(tag.getNamespace(), tag.getKey()))).build()); ++ } ++ } ++ return predicates; ++ } ++ ++ private static Set convertToLegacyNamespaced(final Collection predicates) { ++ final Set namespaceds = Sets.newHashSet(); ++ for (final net.minecraft.advancements.critereon.BlockPredicate predicate : predicates) { ++ if (predicate.blocks().isEmpty()) { ++ continue; ++ } ++ final net.minecraft.core.HolderSet holders = predicate.blocks().get(); ++ if (holders instanceof final net.minecraft.core.HolderSet.Named named) { ++ namespaceds.add(new com.destroystokyo.paper.NamespacedTag(named.key().location().getNamespace(), named.key().location().getPath())); ++ } else { ++ holders.forEach(h -> { ++ h.unwrapKey().ifPresent(key -> { ++ namespaceds.add(new org.bukkit.NamespacedKey(key.location().getNamespace(), key.location().getPath())); ++ }); ++ }); ++ } ++ } ++ return namespaceds; ++ } ++ ++ @Override ++ public boolean hasPlaceableKeys() { ++ return this.canPlaceOnPredicates != null; ++ } ++ ++ @Override ++ public boolean hasDestroyableKeys() { ++ return this.canBreakPredicates != null; ++ } ++ ++ // not a fan of this ++ private static boolean ofAcceptableType(final Collection namespacedResources) { ++ for (com.destroystokyo.paper.Namespaced resource : namespacedResources) { ++ if (!(resource instanceof org.bukkit.NamespacedKey || resource instanceof com.destroystokyo.paper.NamespacedTag)) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ // Paper end - Add an API for can-place-on/can-break adventure mode predicates + } +diff --git a/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java b/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java ++++ b/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java +@@ -0,0 +0,0 @@ public class MaterialRerouting { + return ItemStack.of(material, amount); + } + // Paper end ++ ++ // Paper start - methods added post 1.13, no-op (https://github.com/PaperMC/Paper/pull/1015) ++ public static Set getCanDestroy(final ItemMeta meta) { ++ return meta.getCanDestroy(); ++ } ++ ++ public static void setCanDestroy(final ItemMeta meta, final Set materials) { ++ meta.setCanDestroy(materials); ++ } ++ ++ public static Set getCanPlaceOn(final ItemMeta meta) { ++ return meta.getCanPlaceOn(); ++ } ++ ++ public static void setCanPlaceOn(final ItemMeta meta, final Set materials) { ++ meta.setCanPlaceOn(materials); ++ } ++ // Paper end + } diff --git a/patches/server/Adopt-MaterialRerouting.patch b/patches/server/Adopt-MaterialRerouting.patch index 440fc103c3..a5da1f304d 100644 --- a/patches/server/Adopt-MaterialRerouting.patch +++ b/patches/server/Adopt-MaterialRerouting.patch @@ -74,12 +74,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return com.destroystokyo.paper.event.player.PlayerArmorChangeEvent.SlotType.isEquipable(MaterialRerouting.transformToItemType(material)); + } + -+ // Method added post 1.13, no-op (https://github.com/PaperMC/Paper/pull/1244)1 ++ // Method added post 1.13, no-op (https://github.com/PaperMC/Paper/pull/1244) + public static Material getMaterial(final com.destroystokyo.paper.event.block.AnvilDamagedEvent.DamageState damageState) { + return damageState.getMaterial(); + } + -+ // Method added post 1.13, no-op (https://github.com/PaperMC/Paper/pull/1244)1 ++ // Method added post 1.13, no-op (https://github.com/PaperMC/Paper/pull/1244) + @RerouteStatic("com/destroystokyo/paper/event/block/AnvilDamagedEvent$DamageState") + public static com.destroystokyo.paper.event.block.AnvilDamagedEvent.DamageState getState( + final Material material