From 49f9f6f2cd780cd34bded305bbe406377966a99c Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Sat, 23 Dec 2023 13:16:27 -0800 Subject: [PATCH] Add Registry#getKey (#10066) Some types that have registries support existing without being in a registry and therefore have no key. This is part one of supporting that, adding a Registry#getKey(Object) method to be able to get the key for an object so we can remove Keyed from such objects. This also deprecates Keyed#getKey on TrimMaterial and TrimPattern as these are the 2 offending types currently in the api. --- patches/api/0451-Improve-Registry.patch | 114 +++++++++++++++++++++ patches/server/1054-Improve-Registry.patch | 102 ++++++++++++++++++ 2 files changed, 216 insertions(+) create mode 100644 patches/api/0451-Improve-Registry.patch create mode 100644 patches/server/1054-Improve-Registry.patch diff --git a/patches/api/0451-Improve-Registry.patch b/patches/api/0451-Improve-Registry.patch new file mode 100644 index 000000000..1082efe43 --- /dev/null +++ b/patches/api/0451-Improve-Registry.patch @@ -0,0 +1,114 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 20 Dec 2023 02:03:10 -0800 +Subject: [PATCH] Improve Registry + +Adds Registry#getKey(Object) which should be the +primary way people get the key for an object. Registry +items need to exist without having a key and so +getKey() methods on Keyed objects that have a registry +are marked as Deprecated or Obsolete. + +diff --git a/src/main/java/org/bukkit/Registry.java b/src/main/java/org/bukkit/Registry.java +index 800d23bb249e19d5cf924e7ba36684068624da02..57e97b424cebd205cb260556ab9fb9eb2ff1eebc 100644 +--- a/src/main/java/org/bukkit/Registry.java ++++ b/src/main/java/org/bukkit/Registry.java +@@ -307,6 +307,49 @@ public interface Registry extends Iterable { + @Nullable + T get(@NotNull NamespacedKey key); + ++ // Paper start - improve Registry ++ /** ++ * Gets the key for this object or throws if it doesn't exist. ++ *

++ * Some types can exist without being in a registry ++ * and such will have no key associated with them. This ++ * method throw an exception if it isn't in this registry. ++ * ++ * @param value the value to get the key of in this registry ++ * @return the key for the value ++ * @throws java.util.NoSuchElementException if the value doesn't exist in this registry ++ * @see #getKey(Keyed) ++ */ ++ default @NotNull NamespacedKey getKeyOrThrow(final @NotNull T value) { ++ Preconditions.checkArgument(value != null, "value cannot be null"); ++ final NamespacedKey key = this.getKey(value); ++ if (key == null) { ++ throw new java.util.NoSuchElementException(value + " has no key in " + this); ++ } ++ return key; ++ } ++ ++ /** ++ * Get the key for this object. ++ *

++ * Some types can exist without being in a registry ++ * and such will have no key associated with them. This ++ * method will return null. ++ * ++ * @param value the value to get the key of in this registry ++ * @return the key for the value or null if not in the registry ++ * @see #getKeyOrThrow(Keyed) ++ */ ++ default @Nullable NamespacedKey getKey(final @NotNull T value) { ++ Preconditions.checkArgument(value != null, "value cannot be null"); ++ //noinspection ConstantValue (it might not be in the future...) ++ if (value instanceof Keyed) { ++ return value.getKey(); ++ } ++ return null; ++ } ++ // Paper end - improve Registry ++ + /** + * Returns a new stream, which contains all registry items, which are registered to the registry. + * +@@ -373,5 +416,12 @@ public interface Registry extends Iterable { + public Iterator iterator() { + return map.values().iterator(); + } ++ ++ // Paper start - improve Registry ++ @Override ++ public @NotNull NamespacedKey getKey(final @NotNull T value) { ++ return value.getKey(); ++ } ++ // Paper end - improve Registry + } + } +diff --git a/src/main/java/org/bukkit/inventory/meta/trim/TrimMaterial.java b/src/main/java/org/bukkit/inventory/meta/trim/TrimMaterial.java +index 4327cbc15b9b88d3a568edbebc69c94638ea0465..178d83cb3ccff2d12477d3c13ca4f108fa17e619 100644 +--- a/src/main/java/org/bukkit/inventory/meta/trim/TrimMaterial.java ++++ b/src/main/java/org/bukkit/inventory/meta/trim/TrimMaterial.java +@@ -50,4 +50,13 @@ public interface TrimMaterial extends Keyed { + * {@link Material#AMETHYST_SHARD}. + */ + public static final TrimMaterial AMETHYST = Registry.TRIM_MATERIAL.get(NamespacedKey.minecraft("amethyst")); ++ // Paper start ++ /** ++ * @deprecated use {@link Registry#getKey(Keyed)} and {@link Registry#TRIM_MATERIAL}. TrimMaterials ++ * can exist without a key. ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.4") ++ @Override ++ org.bukkit.@org.jetbrains.annotations.NotNull NamespacedKey getKey(); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/inventory/meta/trim/TrimPattern.java b/src/main/java/org/bukkit/inventory/meta/trim/TrimPattern.java +index 2365220dc0eb1e130b65e81727ff8768dea3f881..e29fc42ae2b9c555db63d10d20552748e28ba60e 100644 +--- a/src/main/java/org/bukkit/inventory/meta/trim/TrimPattern.java ++++ b/src/main/java/org/bukkit/inventory/meta/trim/TrimPattern.java +@@ -74,4 +74,13 @@ public interface TrimPattern extends Keyed { + * {@link Material#HOST_ARMOR_TRIM_SMITHING_TEMPLATE}. + */ + public static final TrimPattern HOST = Registry.TRIM_PATTERN.get(NamespacedKey.minecraft("host")); ++ // Paper start ++ /** ++ * @deprecated use {@link Registry#getKey(Keyed)} and {@link Registry#TRIM_PATTERN}. TrimPatterns ++ * can exist without a key. ++ */ ++ @Deprecated(forRemoval = true, since = "1.20.4") ++ @Override ++ org.bukkit.@org.jetbrains.annotations.NotNull NamespacedKey getKey(); ++ // Paper end + } diff --git a/patches/server/1054-Improve-Registry.patch b/patches/server/1054-Improve-Registry.patch new file mode 100644 index 000000000..162949848 --- /dev/null +++ b/patches/server/1054-Improve-Registry.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 20 Dec 2023 02:03:05 -0800 +Subject: [PATCH] Improve Registry + + +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java +index 253b4cf66e94faf0bc8861318ae7549f52cd29d1..9131fc3a56819ae3e2d754fbe5d8815c71ab9ab3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java +@@ -84,6 +84,7 @@ public class CraftRegistry implements Registry { + + private final Class bukkitClass; + private final Map cache = new HashMap<>(); ++ private final Map byValue = new java.util.IdentityHashMap<>(); // Paper - improve Registry + private final net.minecraft.core.Registry minecraftRegistry; + private final BiFunction minecraftToBukkit; + private boolean init; +@@ -128,6 +129,7 @@ public class CraftRegistry implements Registry { + } + + this.cache.put(namespacedKey, bukkit); ++ this.byValue.put(bukkit, namespacedKey); // Paper - improve Registry + + return bukkit; + } +@@ -150,4 +152,11 @@ public class CraftRegistry implements Registry { + + return this.minecraftToBukkit.apply(namespacedKey, minecraft); + } ++ ++ // Paper start - improve Registry ++ @Override ++ public NamespacedKey getKey(final B value) { ++ return this.byValue.get(value); ++ } ++ // Paper end - improve Registry + } +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimMaterial.java b/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimMaterial.java +index ff365d4f3745adcfe87a4aa0f8a940decccc0f16..c4a63bdd3eda590945ba0c8e7e6e8b9ba4a60ce3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimMaterial.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimMaterial.java +@@ -17,6 +17,7 @@ public class CraftTrimMaterial implements TrimMaterial { + @Override + @NotNull + public NamespacedKey getKey() { ++ if (true) return java.util.Objects.requireNonNull(org.bukkit.Registry.TRIM_MATERIAL.getKey(this), () -> this + " doesn't have a key"); // Paper + return this.key; + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimPattern.java b/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimPattern.java +index 89449c09a4fbf475805f76cd31a0f9e5c1109210..c062c349bf5129cf9b5f637f09dac13b8f8c1796 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimPattern.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/trim/CraftTrimPattern.java +@@ -17,6 +17,7 @@ public class CraftTrimPattern implements TrimPattern { + @Override + @NotNull + public NamespacedKey getKey() { ++ if (true) return java.util.Objects.requireNonNull(org.bukkit.Registry.TRIM_PATTERN.getKey(this), () -> this + " doesn't have a key"); // Paper + return this.key; + } + +diff --git a/src/test/java/org/bukkit/PerRegistryTest.java b/src/test/java/org/bukkit/PerRegistryTest.java +index 9e553a8858750c494456f04abd7bffd1d257308c..6e3062da8840fc7118b59ddb0d6871c9a3178584 100644 +--- a/src/test/java/org/bukkit/PerRegistryTest.java ++++ b/src/test/java/org/bukkit/PerRegistryTest.java +@@ -46,19 +46,22 @@ public class PerRegistryTest extends AbstractTestingBase { + + @ParameterizedTest + @MethodSource("data") +- public void testGet(Registry registry) { ++ public void testGet(Registry registry) { // Paper - improve Registry + registry.forEach(element -> { ++ NamespacedKey key = registry.getKey(element); // Paper - improve Registry ++ assertNotNull(key); // Paper - improve Registry + // Values in the registry should be referentially equal to what is returned with #get() + // This ensures that new instances are not created each time #get() is invoked +- assertSame(element, registry.get(element.getKey())); ++ assertSame(element, registry.get(key)); // Paper - improve Registry + }); + } + + @ParameterizedTest + @MethodSource("data") +- public void testMatch(Registry registry) { ++ public void testMatch(Registry registry) { // Paper - improve Registry + registry.forEach(element -> { +- NamespacedKey key = element.getKey(); ++ NamespacedKey key = registry.getKey(element); // Paper - improve Registry ++ assertNotNull(key); // Paper - improve Registry + + this.assertSameMatchWithKeyMessage(registry, element, key.toString()); // namespace:key + this.assertSameMatchWithKeyMessage(registry, element, key.getKey()); // key +@@ -69,7 +72,7 @@ public class PerRegistryTest extends AbstractTestingBase { + }); + } + +- private void assertSameMatchWithKeyMessage(Registry registry, Keyed element, String key) { ++ private void assertSameMatchWithKeyMessage(Registry registry, T element, String key) { // Paper - improve Registry + assertSame(element, registry.match(key), key); + } +