diff options
Diffstat (limited to 'patches/api/0479-RegistrySet-API.patch')
-rw-r--r-- | patches/api/0479-RegistrySet-API.patch | 486 |
1 files changed, 486 insertions, 0 deletions
diff --git a/patches/api/0479-RegistrySet-API.patch b/patches/api/0479-RegistrySet-API.patch new file mode 100644 index 0000000000..7f310e04cb --- /dev/null +++ b/patches/api/0479-RegistrySet-API.patch @@ -0,0 +1,486 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic <[email protected]> +Date: Sat, 11 May 2024 19:25:48 -0700 +Subject: [PATCH] RegistrySet API + +This API is supposed to be the API equivalent of nms' +HolderSet and HolderSet$Named. + +diff --git a/src/main/java/io/papermc/paper/registry/set/RegistryKeySet.java b/src/main/java/io/papermc/paper/registry/set/RegistryKeySet.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2a36c5ec0da05c7ff19023c542e4b6b04326b8ee +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/set/RegistryKeySet.java +@@ -0,0 +1,40 @@ ++package io.papermc.paper.registry.set; ++ ++import io.papermc.paper.registry.TypedKey; ++import io.papermc.paper.registry.tag.Tag; ++import java.util.Collection; ++import org.bukkit.Keyed; ++import org.bukkit.Registry; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Unmodifiable; ++ ++public non-sealed interface RegistryKeySet<T extends Keyed> extends RegistrySet<T> { // TODO remove Keyed ++ ++ @Override ++ default int size() { ++ return this.values().size(); ++ } ++ ++ /** ++ * Get the keys for the values in this set. ++ * ++ * @return the keys ++ */ ++ @NonNull @Unmodifiable Collection<TypedKey<T>> values(); ++ ++ /** ++ * Resolve this set into a collection of values. Depending on the use ++ * case, it may be better to specifically check if this set is a ++ * {@link RegistryKeySet} or a {@link RegistryValueSet} and access ++ * the keys or values, respectively, directly. May ++ * fail if called too early or a registered value is missing. ++ * ++ * @return the resolved values ++ * @see RegistryKeySet#values() ++ * @see RegistryValueSet#values() ++ */ ++ @NonNull @Unmodifiable Collection<T> resolve(final @NonNull Registry<T> registry); ++} +diff --git a/src/main/java/io/papermc/paper/registry/set/RegistryKeySetImpl.java b/src/main/java/io/papermc/paper/registry/set/RegistryKeySetImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c712181ad4c6a9d00bc04f8a48515a388c692f48 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/set/RegistryKeySetImpl.java +@@ -0,0 +1,53 @@ ++package io.papermc.paper.registry.set; ++ ++import com.google.common.base.Preconditions; ++import io.papermc.paper.registry.RegistryAccess; ++import io.papermc.paper.registry.RegistryKey; ++import io.papermc.paper.registry.TypedKey; ++import java.util.ArrayList; ++import java.util.Collection; ++import java.util.Collections; ++import java.util.List; ++import org.bukkit.Keyed; ++import org.bukkit.NamespacedKey; ++import org.bukkit.Registry; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.framework.qual.DefaultQualifier; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Nullable; ++ ++@DefaultQualifier(NonNull.class) ++record RegistryKeySetImpl<T extends Keyed>(RegistryKey<T> registryKey, List<TypedKey<T>> values) implements RegistryKeySet<T> { // TODO remove Keyed ++ ++ static <T extends Keyed> RegistryKeySet<T> create(final RegistryKey<T> registryKey, final Iterable<? extends T> values) { // TODO remove Keyed ++ final Registry<T> registry = RegistryAccess.registryAccess().getRegistry(registryKey); ++ final ArrayList<TypedKey<T>> keys = new ArrayList<>(); ++ for (final T value : values) { ++ final @Nullable NamespacedKey key = registry.getKey(value); ++ Preconditions.checkArgument(key != null, value + " does not have a key in " + registryKey); ++ keys.add(TypedKey.create(registryKey, key)); ++ } ++ return new RegistryKeySetImpl<>(registryKey, keys); ++ } ++ ++ RegistryKeySetImpl { ++ values = List.copyOf(values); ++ } ++ ++ @Override ++ public boolean contains(final TypedKey<T> valueKey) { ++ return this.values.contains(valueKey); ++ } ++ ++ @Override ++ public Collection<T> resolve(final Registry<T> registry) { ++ final List<T> values = new ArrayList<>(this.values.size()); ++ for (final TypedKey<T> key : this.values) { ++ final @Nullable T value = registry.get(key.key()); ++ Preconditions.checkState(value != null, "Trying to access unbound TypedKey: " + key); ++ values.add(value); ++ } ++ return Collections.unmodifiableList(values); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/set/RegistrySet.java b/src/main/java/io/papermc/paper/registry/set/RegistrySet.java +new file mode 100644 +index 0000000000000000000000000000000000000000..f414df1a114f9d727c27fecc55712b6f5ff415fb +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/set/RegistrySet.java +@@ -0,0 +1,101 @@ ++package io.papermc.paper.registry.set; ++ ++import com.google.common.collect.Lists; ++import io.papermc.paper.registry.RegistryKey; ++import io.papermc.paper.registry.TypedKey; ++import io.papermc.paper.registry.tag.Tag; ++import java.util.Collection; ++import java.util.Iterator; ++import org.bukkit.Keyed; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Contract; ++import org.jetbrains.annotations.Unmodifiable; ++ ++/** ++ * Represents a collection tied to a registry. ++ * <p> ++ * There are 2<!--3--> types of registry sets: ++ * <ul> ++ * <li>{@link Tag} which is a tag from vanilla or a datapack. ++ * These are obtained via {@link org.bukkit.Registry#getTag(io.papermc.paper.registry.tag.TagKey)}.</li> ++ * <li>{@link RegistryKeySet} which is a set of of values that are present in the registry. These are ++ * created via {@link #keySet(RegistryKey, Iterable)} or {@link #keySetFromValues(RegistryKey, Iterable)}.</li> ++ * <!-- <li>{@link RegistryValueSet} which is a set of values which are anonymous (don't have keys in the registry). These are ++ * created via {@link #valueSet(RegistryKey, Iterable)}.</li>--> ++ * </ul> ++ * ++ * @param <T> registry value type ++ */ ++public sealed interface RegistrySet<T> permits RegistryKeySet, RegistryValueSet { ++ ++ // TODO uncomment when direct holder sets need to be exposed to the API ++ // /** ++ // * Creates a {@link RegistryValueSet} from anonymous values. ++ // * <p>All values provided <b>must not</b> have keys in the given registry.</p> ++ // * ++ // * @param registryKey the registry key for the type of these values ++ // * @param values the values ++ // * @return a new registry set ++ // * @param <T> the type of the values ++ // */ ++ // @Contract(value = "_, _ -> new", pure = true) ++ // static <T> @NonNull RegistryValueSet<T> valueSet(final @NonNull RegistryKey<T> registryKey, final @NonNull Iterable<? extends T> values) { ++ // return RegistryValueSetImpl.create(registryKey, values); ++ // } ++ ++ /** ++ * Creates a {@link RegistryKeySet} from registry-backed values. ++ * <p>All values provided <b>must</b> have keys in the given registry. ++ * <!--For anonymous values, use {@link #valueSet(RegistryKey, Iterable)}--></p> ++ * <p>If references to actual objects are not available yet, use {@link #keySet(RegistryKey, Iterable)} to ++ * create an equivalent {@link RegistryKeySet} using just {@link TypedKey TypedKeys}.</p> ++ * ++ * @param registryKey the registry key for the owner of these values ++ * @param values the values ++ * @return a new registry set ++ * @param <T> the type of the values ++ * @throws IllegalArgumentException if the registry isn't available yet or if any value doesn't have a key in that registry ++ */ ++ @Contract(value = "_, _ -> new", pure = true) ++ static <T extends Keyed> @NonNull RegistryKeySet<T> keySetFromValues(final @NonNull RegistryKey<T> registryKey, final @NonNull Iterable<? extends T> values) { // TODO remove Keyed ++ return RegistryKeySetImpl.create(registryKey, values); ++ } ++ ++ /** ++ * Creates a direct {@link RegistrySet} from {@link TypedKey TypedKeys}. ++ * ++ * @param registryKey the registry key for the owner of these keys ++ * @param keys the keys for the values ++ * @return a new registry set ++ * @param <T> the type of the values ++ */ ++ @SuppressWarnings("BoundedWildcard") ++ @Contract(value = "_, _ -> new", pure = true) ++ static <T extends Keyed> @NonNull RegistryKeySet<T> keySet(final @NonNull RegistryKey<T> registryKey, final @NonNull Iterable<TypedKey<T>> keys) { // TODO remove Keyed ++ return new RegistryKeySetImpl<>(registryKey, Lists.newArrayList(keys)); ++ } ++ ++ /** ++ * Get the registry key for this set. ++ * ++ * @return the registry key ++ */ ++ @NonNull RegistryKey<T> registryKey(); ++ ++ /** ++ * Get the size of this set. ++ * ++ * @return the size ++ */ ++ int size(); ++ ++ /** ++ * Checks if this set contains the value with the given key. ++ * ++ * @param valueKey the key to check ++ * @return true if the value is in this set ++ */ ++ boolean contains(@NonNull TypedKey<T> valueKey); ++} +diff --git a/src/main/java/io/papermc/paper/registry/set/RegistryValueSet.java b/src/main/java/io/papermc/paper/registry/set/RegistryValueSet.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9cbbb507738a4cdcd9f48a36ac00d2d5628a7f94 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/set/RegistryValueSet.java +@@ -0,0 +1,45 @@ ++package io.papermc.paper.registry.set; ++ ++import io.papermc.paper.registry.TypedKey; ++import java.util.Collection; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Contract; ++import org.jetbrains.annotations.Unmodifiable; ++ ++/** ++ * A collection of anonymous values relating to a registry. These ++ * are values of the same type as the registry, but will not be found ++ * in the registry, hence, anonymous. ++ * @param <T> registry value type ++ */ ++public sealed interface RegistryValueSet<T> extends RegistrySet<T> permits RegistryValueSetImpl { ++ ++ @Override ++ default int size() { ++ return this.values().size(); ++ } ++ ++ /** ++ * {@inheritDoc} ++ * <p>Will always return false because these are anonymous values</p> ++ */ ++ @Contract("_ -> false") ++ @Override ++ default boolean contains(final @NonNull TypedKey<T> valueKey) { ++ return false; ++ } ++ ++ @Override ++ default @NonNull @Unmodifiable Collection<T> resolve() { ++ return this.values(); ++ } ++ ++ /** ++ * Get the collection of values in this direct set. ++ * ++ * @return the values ++ */ ++ @NonNull @Unmodifiable Collection<T> values(); ++} +diff --git a/src/main/java/io/papermc/paper/registry/set/RegistryValueSetImpl.java b/src/main/java/io/papermc/paper/registry/set/RegistryValueSetImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4ce5b26a1fcaae7b28ac8ed3c25014b66c266318 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/set/RegistryValueSetImpl.java +@@ -0,0 +1,18 @@ ++package io.papermc.paper.registry.set; ++ ++import com.google.common.collect.Lists; ++import io.papermc.paper.registry.RegistryKey; ++import java.util.List; ++import org.jetbrains.annotations.ApiStatus; ++ ++record RegistryValueSetImpl<T>(RegistryKey<T> registryKey, List<T> values) implements RegistryValueSet<T> { ++ ++ RegistryValueSetImpl { ++ values = List.copyOf(values); ++ } ++ ++ static <T> RegistryValueSet<T> create(final RegistryKey<T> registryKey, final Iterable<? extends T> values) { ++ return new RegistryValueSetImpl<>(registryKey, Lists.newArrayList(values)); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/tag/Tag.java b/src/main/java/io/papermc/paper/registry/tag/Tag.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5fce47a5a8a46f9f144d9adb4257a00a4ea84315 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/tag/Tag.java +@@ -0,0 +1,24 @@ ++package io.papermc.paper.registry.tag; ++ ++import io.papermc.paper.registry.set.RegistryKeySet; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.jetbrains.annotations.ApiStatus; ++ ++/** ++ * A named {@link RegistryKeySet} which are created ++ * via the datapack tag system. ++ * ++ * @param <T> ++ * @see org.bukkit.Tag ++ * @see org.bukkit.Registry#getTag(TagKey) ++ */ ++public interface Tag<T> extends RegistryKeySet<T> { ++ ++ /** ++ * Get the identifier for this named set. ++ * ++ * @return the tag key identifier ++ */ ++ @NonNull TagKey<T> tagKey(); ++} +diff --git a/src/main/java/io/papermc/paper/registry/tag/TagKey.java b/src/main/java/io/papermc/paper/registry/tag/TagKey.java +new file mode 100644 +index 0000000000000000000000000000000000000000..a49d328e95f7fda6567ee6c4f5f1878a2c187277 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/tag/TagKey.java +@@ -0,0 +1,32 @@ ++package io.papermc.paper.registry.tag; ++ ++import io.papermc.paper.registry.RegistryKey; ++import net.kyori.adventure.key.Key; ++import net.kyori.adventure.key.Keyed; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Contract; ++ ++public sealed interface TagKey<T> extends Keyed permits TagKeyImpl { ++ ++ /** ++ * Creates a new tag key for a registry. ++ * ++ * @param registryKey the registry for the tag ++ * @param key the specific key for the tag ++ * @return a new tag key ++ * @param <T> the registry value type ++ */ ++ @Contract(value = "_, _ -> new", pure = true) ++ static <T> @NonNull TagKey<T> create(final @NonNull RegistryKey<T> registryKey, final @NonNull Key key) { ++ return new TagKeyImpl<>(registryKey, key); ++ } ++ ++ /** ++ * Get the registry key for this tag key. ++ * ++ * @return the registry key ++ */ ++ @NonNull RegistryKey<T> registryKey(); ++} +diff --git a/src/main/java/io/papermc/paper/registry/tag/TagKeyImpl.java b/src/main/java/io/papermc/paper/registry/tag/TagKeyImpl.java +new file mode 100644 +index 0000000000000000000000000000000000000000..11d19e339c7c62f2eb4467277552c27e4e83069c +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/tag/TagKeyImpl.java +@@ -0,0 +1,12 @@ ++package io.papermc.paper.registry.tag; ++ ++import io.papermc.paper.registry.RegistryKey; ++import net.kyori.adventure.key.Key; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.framework.qual.DefaultQualifier; ++import org.jetbrains.annotations.ApiStatus; ++ ++@DefaultQualifier(NonNull.class) ++record TagKeyImpl<T>(RegistryKey<T> registryKey, Key key) implements TagKey<T> { ++} +diff --git a/src/main/java/org/bukkit/Registry.java b/src/main/java/org/bukkit/Registry.java +index 240500771bac439156b4c5d93ff047ae45d56154..dd937b18f93987f4c481d154bb263ef194bd4dc4 100644 +--- a/src/main/java/org/bukkit/Registry.java ++++ b/src/main/java/org/bukkit/Registry.java +@@ -146,7 +146,23 @@ public interface Registry<T extends Keyed> extends Iterable<T> { + * + * @see EntityType + */ +- Registry<EntityType> ENTITY_TYPE = new SimpleRegistry<>(EntityType.class, (entity) -> entity != EntityType.UNKNOWN); ++ // Paper start - support tags here ++ Registry<EntityType> ENTITY_TYPE = new SimpleRegistry<>(EntityType.class, (entity) -> entity != EntityType.UNKNOWN) { ++ @Override ++ public boolean hasTag(final io.papermc.paper.registry.tag.@NotNull TagKey<EntityType> key) { ++ return Bukkit.getUnsafe().getTag(key) != null; ++ } ++ ++ @Override ++ public io.papermc.paper.registry.tag.@NotNull Tag<EntityType> getTag(final io.papermc.paper.registry.tag.@NotNull TagKey<EntityType> key) { ++ final io.papermc.paper.registry.tag.Tag<EntityType> tag = Bukkit.getUnsafe().getTag(key); ++ if (tag == null) { ++ throw new java.util.NoSuchElementException("No tag " + key + " found"); ++ } ++ return tag; ++ } ++ }; ++ // Paper end - support tags here + /** + * Server instruments. + * +@@ -290,7 +306,23 @@ public interface Registry<T extends Keyed> extends Iterable<T> { + * + * @see Fluid + */ +- Registry<Fluid> FLUID = new SimpleRegistry<>(Fluid.class); ++ // Paper start - support tags here ++ Registry<Fluid> FLUID = new SimpleRegistry<>(Fluid.class) { ++ @Override ++ public boolean hasTag(final io.papermc.paper.registry.tag.@NotNull TagKey<Fluid> key) { ++ return Bukkit.getUnsafe().getTag(key) != null; ++ } ++ ++ @Override ++ public io.papermc.paper.registry.tag.@NotNull Tag<Fluid> getTag(final io.papermc.paper.registry.tag.@NotNull TagKey<Fluid> key) { ++ final io.papermc.paper.registry.tag.Tag<Fluid> tag = Bukkit.getUnsafe().getTag(key); ++ if (tag == null) { ++ throw new java.util.NoSuchElementException("No tag " + key + " found"); ++ } ++ return tag; ++ } ++ }; ++ // Paper end - support tags here + /** + * Frog variants. + * +@@ -448,6 +480,30 @@ public interface Registry<T extends Keyed> extends Iterable<T> { + } + // Paper end - improve Registry + ++ // Paper start - RegistrySet API ++ /** ++ * Checks if this registry has a tag with the given key. ++ * ++ * @param key the key to check for ++ * @return true if this registry has a tag with the given key, false otherwise ++ */ ++ @ApiStatus.Experimental ++ default boolean hasTag(final io.papermc.paper.registry.tag.@NotNull TagKey<T> key) { ++ throw new UnsupportedOperationException(this + " doesn't have tags"); ++ } ++ ++ /** ++ * Gets the named registry set (tag) for the given key. ++ * ++ * @param key the key to get the tag for ++ * @return the tag for the key ++ */ ++ @ApiStatus.Experimental ++ default @NotNull io.papermc.paper.registry.tag.Tag<T> getTag(final io.papermc.paper.registry.tag.@NotNull TagKey<T> key) { ++ throw new UnsupportedOperationException(this + " doesn't have tags"); ++ } ++ // Paper end - RegistrySet API ++ + /** + * Returns a new stream, which contains all registry items, which are registered to the registry. + * +@@ -477,7 +533,7 @@ public interface Registry<T extends Keyed> extends Iterable<T> { + return (namespacedKey != null) ? get(namespacedKey) : null; + } + +- static final class SimpleRegistry<T extends Enum<T> & Keyed> implements Registry<T> { ++ static class SimpleRegistry<T extends Enum<T> & Keyed> implements Registry<T> { // Paper - not final + + private final Class<T> type; + private final Map<NamespacedKey, T> map; +diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java +index 0e9ccfee7a03d341e7c4d271f53b4ed168b404ef..7332034bb1753f48f7904dafab1ef4b3ee117ea3 100644 +--- a/src/main/java/org/bukkit/UnsafeValues.java ++++ b/src/main/java/org/bukkit/UnsafeValues.java +@@ -275,4 +275,6 @@ public interface UnsafeValues { + // Paper end - lifecycle event API + + @NotNull java.util.List<net.kyori.adventure.text.Component> computeTooltipLines(@NotNull ItemStack itemStack, @NotNull io.papermc.paper.inventory.tooltip.TooltipContext tooltipContext, @Nullable org.bukkit.entity.Player player); // Paper - expose itemstack tooltip lines ++ ++ <A extends Keyed, M> io.papermc.paper.registry.tag.@Nullable Tag<A> getTag(io.papermc.paper.registry.tag.@NotNull TagKey<A> tagKey); // Paper - hack to get tags for non-server backed registries + } |