diff options
Diffstat (limited to 'patches/api/0473-Introduce-registry-entry-and-builders.patch')
-rw-r--r-- | patches/api/0473-Introduce-registry-entry-and-builders.patch | 501 |
1 files changed, 501 insertions, 0 deletions
diff --git a/patches/api/0473-Introduce-registry-entry-and-builders.patch b/patches/api/0473-Introduce-registry-entry-and-builders.patch new file mode 100644 index 0000000000..2731a371af --- /dev/null +++ b/patches/api/0473-Introduce-registry-entry-and-builders.patch @@ -0,0 +1,501 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Bjarne Koll <[email protected]> +Date: Thu, 13 Jun 2024 22:35:05 +0200 +Subject: [PATCH] Introduce registry entry and builders + + +diff --git a/src/main/java/io/papermc/paper/registry/RegistryKey.java b/src/main/java/io/papermc/paper/registry/RegistryKey.java +index 8410d7213370f01cbedbf7fac29bac96f150c49a..d8716f855806471728c35b3ec34efb808a5146cf 100644 +--- a/src/main/java/io/papermc/paper/registry/RegistryKey.java ++++ b/src/main/java/io/papermc/paper/registry/RegistryKey.java +@@ -79,9 +79,10 @@ public sealed interface RegistryKey<T> extends Keyed permits RegistryKeyImpl { + @ApiStatus.Internal + RegistryKey<BlockType> BLOCK = create("block"); + /** +- * @apiNote DO NOT USE ++ * @apiNote use preferably only in the context of registry entries. ++ * @see io.papermc.paper.registry.data + */ +- @ApiStatus.Internal ++ @ApiStatus.Experimental // Paper - already required for registry builders + RegistryKey<ItemType> ITEM = create("item"); + /** + * Built-in registry for cat variants. +diff --git a/src/main/java/io/papermc/paper/registry/data/EnchantmentRegistryEntry.java b/src/main/java/io/papermc/paper/registry/data/EnchantmentRegistryEntry.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d0d19a4bb2ba0e92710861b106777a428bdc5ad9 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/data/EnchantmentRegistryEntry.java +@@ -0,0 +1,332 @@ ++package io.papermc.paper.registry.data; ++ ++import io.papermc.paper.registry.RegistryBuilder; ++import io.papermc.paper.registry.RegistryKey; ++import io.papermc.paper.registry.TypedKey; ++import io.papermc.paper.registry.set.RegistryKeySet; ++import io.papermc.paper.registry.set.RegistrySet; ++import io.papermc.paper.registry.tag.TagKey; ++import java.util.List; ++import net.kyori.adventure.text.Component; ++import org.bukkit.enchantments.Enchantment; ++import org.bukkit.inventory.EquipmentSlotGroup; ++import org.bukkit.inventory.ItemType; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Contract; ++import org.jetbrains.annotations.Range; ++import org.jetbrains.annotations.Unmodifiable; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++/** ++ * A data-centric version-specific registry entry for the {@link Enchantment} type. ++ */ ++@NullMarked ++public interface EnchantmentRegistryEntry { ++ ++ /** ++ * Provides the description of this enchantment entry as displayed to the client, e.g. "Sharpness" for the sharpness ++ * enchantment. ++ * ++ * @return the description component. ++ */ ++ Component description(); ++ ++ /** ++ * Provides the registry key set referencing the items this enchantment is supported on. ++ * ++ * @return the registry key set. ++ */ ++ RegistryKeySet<ItemType> supportedItems(); ++ ++ /** ++ * Provides the registry key set referencing the item types this enchantment can be applied to when ++ * enchanting in an enchantment table. ++ * <p> ++ * If this value is {@code null}, {@link #supportedItems()} will be sourced instead in the context of an enchantment table. ++ * Additionally, the tag {@link io.papermc.paper.registry.keys.tags.EnchantmentTagKeys#IN_ENCHANTING_TABLE} defines ++ * which enchantments can even show up in an enchantment table. ++ * ++ * @return the registry key set. ++ */ ++ @Nullable RegistryKeySet<ItemType> primaryItems(); ++ ++ /** ++ * Provides the weight of this enchantment used by the weighted random when selecting enchantments. ++ * ++ * @return the weight value. ++ * @see <a href="https://minecraft.wiki/w/Enchanting">https://minecraft.wiki/w/Enchanting</a> for examplary weights. ++ */ ++ @Range(from = 1, to = 1024) int weight(); ++ ++ /** ++ * Provides the maximum level this enchantment can have when applied. ++ * ++ * @return the maximum level. ++ */ ++ @Range(from = 1, to = 255) int maxLevel(); ++ ++ /** ++ * Provides the minimum cost needed to enchant an item with this enchantment. ++ * <p> ++ * Note that a cost is not directly related to the consumed xp. ++ * ++ * @return the enchantment cost. ++ * @see <a href="https://minecraft.wiki/w/Enchanting/Levels">https://minecraft.wiki/w/Enchanting/Levels</a> for ++ * examplary costs. ++ */ ++ EnchantmentCost minimumCost(); ++ ++ /** ++ * Provides the maximum cost allowed to enchant an item with this enchantment. ++ * <p> ++ * Note that a cost is not directly related to the consumed xp. ++ * ++ * @return the enchantment cost. ++ * @see <a href="https://minecraft.wiki/w/Enchanting/Levels">https://minecraft.wiki/w/Enchanting/Levels</a> for ++ * examplary costs. ++ */ ++ EnchantmentCost maximumCost(); ++ ++ /** ++ * Provides the cost of applying this enchantment using an anvil. ++ * <p> ++ * Note that this is halved when using an enchantment book, and is multiplied by the level of the enchantment. ++ * See <a href="https://minecraft.wiki/w/Anvil_mechanics">https://minecraft.wiki/w/Anvil_mechanics</a> for more ++ * information. ++ * </p> ++ * ++ * @return the anvil cost of this enchantment ++ */ ++ @Range(from = 0, to = Integer.MAX_VALUE) int anvilCost(); ++ ++ /** ++ * Provides a list of slot groups this enchantment may be active in. ++ * <p> ++ * If the item enchanted with this enchantment is equipped in a slot not covered by the returned list and its ++ * groups, the enchantment's effects, like attribute modifiers, will not activate. ++ * ++ * @return a list of equipment slot groups. ++ * @see Enchantment#getActiveSlotGroups() ++ */ ++ @Unmodifiable List<EquipmentSlotGroup> activeSlots(); ++ ++ /** ++ * Provides the registry key set of enchantments that this enchantment is exclusive with. ++ * <p> ++ * Exclusive enchantments prohibit the application of this enchantment to an item if they are already present on ++ * said item. ++ * ++ * @return a registry set of enchantments exclusive to this one. ++ */ ++ RegistryKeySet<Enchantment> exclusiveWith(); ++ ++ /** ++ * A mutable builder for the {@link EnchantmentRegistryEntry} plugins may change in applicable registry events. ++ * <p> ++ * The following values are required for each builder: ++ * <ul> ++ * <li>{@link #description(Component)}</li> ++ * <li>{@link #supportedItems(RegistryKeySet)}</li> ++ * <li>{@link #weight(int)}</li> ++ * <li>{@link #maxLevel(int)}</li> ++ * <li>{@link #minimumCost(EnchantmentCost)}</li> ++ * <li>{@link #maximumCost(EnchantmentCost)}</li> ++ * <li>{@link #anvilCost(int)}</li> ++ * <li>{@link #activeSlots(Iterable)}</li> ++ * </ul> ++ */ ++ @ApiStatus.Experimental ++ @ApiStatus.NonExtendable ++ interface Builder extends EnchantmentRegistryEntry, RegistryBuilder<Enchantment> { ++ ++ /** ++ * Configures the description of this enchantment entry as displayed to the client, e.g. "Sharpness" for the ++ * sharpness enchantment. ++ * ++ * @param description the description component. ++ * @return this builder. ++ */ ++ @Contract(value = "_ -> this", mutates = "this") ++ Builder description(Component description); ++ ++ /** ++ * Configures the set of supported items this enchantment can be applied on. This ++ * can be a {@link RegistryKeySet} created via {@link RegistrySet#keySet(io.papermc.paper.registry.RegistryKey, Iterable)} or ++ * a tag obtained via {@link io.papermc.paper.registry.event.RegistryFreezeEvent#getOrCreateTag(TagKey)} with ++ * tag keys found in {@link io.papermc.paper.registry.keys.tags.ItemTypeTagKeys} such as ++ * {@link io.papermc.paper.registry.keys.tags.ItemTypeTagKeys#ENCHANTABLE_ARMOR} and ++ * {@link io.papermc.paper.registry.keys.tags.ItemTypeTagKeys#ENCHANTABLE_SWORD}. ++ * ++ * @param supportedItems the registry key set representing the supported items. ++ * @return this builder. ++ * @see RegistrySet#keySet(RegistryKey, TypedKey[]) ++ * @see io.papermc.paper.registry.event.RegistryFreezeEvent#getOrCreateTag(TagKey) ++ */ ++ @Contract(value = "_ -> this", mutates = "this") ++ Builder supportedItems(RegistryKeySet<ItemType> supportedItems); ++ ++ /** ++ * Configures a set of item types this enchantment can naturally be applied to, when enchanting in an ++ * enchantment table.This can be a {@link RegistryKeySet} created via ++ * {@link RegistrySet#keySet(io.papermc.paper.registry.RegistryKey, Iterable)} or a tag obtained via ++ * {@link io.papermc.paper.registry.event.RegistryFreezeEvent#getOrCreateTag(TagKey)} with ++ * tag keys found in {@link io.papermc.paper.registry.keys.tags.ItemTypeTagKeys} such as ++ * {@link io.papermc.paper.registry.keys.tags.ItemTypeTagKeys#ENCHANTABLE_ARMOR} and ++ * {@link io.papermc.paper.registry.keys.tags.ItemTypeTagKeys#ENCHANTABLE_SWORD}. ++ * <p> ++ * Defaults to {@code null} which means all {@link #supportedItems()} are considered primary items. ++ * Additionally, the tag {@link io.papermc.paper.registry.keys.tags.EnchantmentTagKeys#IN_ENCHANTING_TABLE} defines ++ * which enchantments can even show up in an enchantment table. ++ * ++ * @param primaryItems the registry key set representing the primary items. ++ * @return this builder. ++ * @see RegistrySet#keySet(RegistryKey, TypedKey[]) ++ * @see io.papermc.paper.registry.event.RegistryFreezeEvent#getOrCreateTag(TagKey) ++ */ ++ @Contract(value = "_ -> this", mutates = "this") ++ Builder primaryItems(@Nullable RegistryKeySet<ItemType> primaryItems); ++ ++ /** ++ * Configures the weight of this enchantment used by the weighted random when selecting enchantments. ++ * ++ * @param weight the weight value. ++ * @return this builder. ++ * @see <a href="https://minecraft.wiki/w/Enchanting">https://minecraft.wiki/w/Enchanting</a> for examplary weights. ++ */ ++ @Contract(value = "_ -> this", mutates = "this") ++ Builder weight(@Range(from = 1, to = 1024) int weight); ++ ++ /** ++ * Configures the maximum level this enchantment can have when applied. ++ * ++ * @param maxLevel the maximum level. ++ * @return this builder. ++ */ ++ @Contract(value = "_ -> this", mutates = "this") ++ Builder maxLevel(@Range(from = 1, to = 255) int maxLevel); ++ ++ /** ++ * Configures the minimum cost needed to enchant an item with this enchantment. ++ * <p> ++ * Note that a cost is not directly related to the consumed xp. ++ * ++ * @param minimumCost the enchantment cost. ++ * @return this builder. ++ * @see <a href="https://minecraft.wiki/w/Enchanting/Levels">https://minecraft.wiki/w/Enchanting/Levels</a> for ++ * examplary costs. ++ */ ++ @Contract(value = "_ -> this", mutates = "this") ++ Builder minimumCost(EnchantmentCost minimumCost); ++ ++ /** ++ * Configures the maximum cost to enchant an item with this enchantment. ++ * <p> ++ * Note that a cost is not directly related to the consumed xp. ++ * ++ * @param maximumCost the enchantment cost. ++ * @return this builder. ++ * @see <a href="https://minecraft.wiki/w/Enchanting/Levels">https://minecraft.wiki/w/Enchanting/Levels</a> for ++ * examplary costs. ++ */ ++ @Contract(value = "_ -> this", mutates = "this") ++ Builder maximumCost(EnchantmentCost maximumCost); ++ ++ /** ++ * Configures the cost of applying this enchantment using an anvil. ++ * <p> ++ * Note that this is halved when using an enchantment book, and is multiplied by the level of the enchantment. ++ * See <a href="https://minecraft.wiki/w/Anvil_mechanics">https://minecraft.wiki/w/Anvil_mechanics</a> for more information. ++ * </p> ++ * ++ * @param anvilCost the anvil cost of this enchantment ++ * @return this builder. ++ * @see Enchantment#getAnvilCost() ++ */ ++ @Contract(value = "_ -> this", mutates = "this") ++ Builder anvilCost(@Range(from = 0, to = Integer.MAX_VALUE) int anvilCost); ++ ++ /** ++ * Configures the list of slot groups this enchantment may be active in. ++ * <p> ++ * If the item enchanted with this enchantment is equipped in a slot not covered by the returned list and its ++ * groups, the enchantment's effects, like attribute modifiers, will not activate. ++ * ++ * @param activeSlots a list of equipment slot groups. ++ * @return this builder. ++ * @see Enchantment#getActiveSlotGroups() ++ */ ++ @Contract(value = "_ -> this", mutates = "this") ++ default Builder activeSlots(final EquipmentSlotGroup... activeSlots) { ++ return this.activeSlots(List.of(activeSlots)); ++ } ++ ++ /** ++ * Configures the list of slot groups this enchantment may be active in. ++ * <p> ++ * If the item enchanted with this enchantment is equipped in a slot not covered by the returned list and its ++ * groups, the enchantment's effects, like attribute modifiers, will not activate. ++ * ++ * @param activeSlots a list of equipment slot groups. ++ * @return this builder. ++ * @see Enchantment#getActiveSlotGroups() ++ */ ++ @Contract(value = "_ -> this", mutates = "this") ++ Builder activeSlots(Iterable<EquipmentSlotGroup> activeSlots); ++ ++ /** ++ * Configures the registry key set of enchantments that this enchantment is exclusive with. ++ * <p> ++ * Exclusive enchantments prohibit the application of this enchantment to an item if they are already present on ++ * said item. ++ * <p> ++ * Defaults to an empty set allowing this enchantment to be applied regardless of other enchantments. ++ * ++ * @param exclusiveWith a registry set of enchantments exclusive to this one. ++ * @return this builder. ++ * @see RegistrySet#keySet(RegistryKey, TypedKey[]) ++ * @see io.papermc.paper.registry.event.RegistryFreezeEvent#getOrCreateTag(TagKey) ++ */ ++ @Contract(value = "_ -> this", mutates = "this") ++ Builder exclusiveWith(RegistryKeySet<Enchantment> exclusiveWith); ++ } ++ ++ /** ++ * The enchantment cost interface represents the cost of applying an enchantment, split up into its different components. ++ */ ++ interface EnchantmentCost { ++ ++ /** ++ * Returns the base cost of this enchantment cost, no matter what level the enchantment has. ++ * ++ * @return the cost in levels. ++ */ ++ int baseCost(); ++ ++ /** ++ * Returns the additional cost added per level of the enchantment to be applied. ++ * This cost is applied per level above the first. ++ * ++ * @return the cost added to the {@link #baseCost()} for each level above the first. ++ */ ++ int additionalPerLevelCost(); ++ ++ /** ++ * Creates a new enchantment cost instance based on the passed values. ++ * ++ * @param baseCost the base cost of the enchantment cost as returned by {@link #baseCost()} ++ * @param additionalPerLevelCost the additional cost per level, as returned by {@link #additionalPerLevelCost()} ++ * @return the created instance. ++ */ ++ @Contract(value = "_,_ -> new", pure = true) ++ static EnchantmentCost of(final int baseCost, final int additionalPerLevelCost) { ++ record Impl(int baseCost, int additionalPerLevelCost) implements EnchantmentCost { ++ } ++ ++ return new Impl(baseCost, additionalPerLevelCost); ++ } ++ } ++ ++} +diff --git a/src/main/java/io/papermc/paper/registry/data/GameEventRegistryEntry.java b/src/main/java/io/papermc/paper/registry/data/GameEventRegistryEntry.java +new file mode 100644 +index 0000000000000000000000000000000000000000..980fe12b75258b51cc2498590cadb9de80805b1f +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/data/GameEventRegistryEntry.java +@@ -0,0 +1,49 @@ ++package io.papermc.paper.registry.data; ++ ++import io.papermc.paper.registry.RegistryBuilder; ++import org.bukkit.GameEvent; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.Contract; ++import org.jetbrains.annotations.Range; ++import org.jspecify.annotations.NullMarked; ++ ++/** ++ * A data-centric version-specific registry entry for the {@link GameEvent} type. ++ */ ++@NullMarked ++public interface GameEventRegistryEntry { ++ ++ /** ++ * Provides the range in which this game event will notify its listeners. ++ * ++ * @return the range of blocks, represented as an int. ++ * @see GameEvent#getRange() ++ */ ++ @Range(from = 0, to = Integer.MAX_VALUE) int range(); ++ ++ /** ++ * A mutable builder for the {@link GameEventRegistryEntry} plugins may change in applicable registry events. ++ * <p> ++ * The following values are required for each builder: ++ * <ul> ++ * <li>{@link #range(int)}</li> ++ * </ul> ++ */ ++ @ApiStatus.Experimental ++ @ApiStatus.NonExtendable ++ interface Builder extends GameEventRegistryEntry, RegistryBuilder<GameEvent> { ++ ++ /** ++ * Sets the range in which this game event should notify its listeners. ++ * ++ * @param range the range of blocks. ++ * @return this builder instance. ++ * @see GameEventRegistryEntry#range() ++ * @see GameEvent#getRange() ++ */ ++ @Contract(value = "_ -> this", mutates = "this") ++ Builder range(@Range(from = 0, to = Integer.MAX_VALUE) int range); ++ } ++} +diff --git a/src/main/java/io/papermc/paper/registry/data/package-info.java b/src/main/java/io/papermc/paper/registry/data/package-info.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4f8f536f437c5f483ac7bce393e664fd7bc38477 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/data/package-info.java +@@ -0,0 +1,9 @@ ++/** ++ * Collection of registry entry types that may be created or modified via the ++ * {@link io.papermc.paper.registry.event.RegistryEvent}. ++ * <p> ++ * A registry entry represents its runtime API counterpart as a version-specific data-focused type. ++ * Registry entries are not expected to be used during plugin runtime interactions with the API but are mostly ++ * exposed during registry creation/modification. ++ */ ++package io.papermc.paper.registry.data; +diff --git a/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java b/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java +index 91ae9c0d3ec55ce417d4b447bf3d1b0d0c174b5e..1c8e77c7243cfedef6c4d1491cf98e6ec8f1690f 100644 +--- a/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java ++++ b/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java +@@ -1,8 +1,15 @@ + package io.papermc.paper.registry.event; + ++import io.papermc.paper.registry.RegistryKey; ++import io.papermc.paper.registry.data.EnchantmentRegistryEntry; ++import io.papermc.paper.registry.data.GameEventRegistryEntry; ++import org.bukkit.GameEvent; ++import org.bukkit.enchantments.Enchantment; + import org.jetbrains.annotations.ApiStatus; + import org.jspecify.annotations.NullMarked; + ++import static io.papermc.paper.registry.event.RegistryEventProviderImpl.create; ++ + /** + * Holds providers for {@link RegistryEntryAddEvent} and {@link RegistryFreezeEvent} + * handlers for each applicable registry. +@@ -11,6 +18,9 @@ import org.jspecify.annotations.NullMarked; + @NullMarked + public final class RegistryEvents { + ++ public static final RegistryEventProvider<GameEvent, GameEventRegistryEntry.Builder> GAME_EVENT = create(RegistryKey.GAME_EVENT); ++ public static final RegistryEventProvider<Enchantment, EnchantmentRegistryEntry.Builder> ENCHANTMENT = create(RegistryKey.ENCHANTMENT); ++ + private RegistryEvents() { + } + } +diff --git a/src/main/java/org/bukkit/GameEvent.java b/src/main/java/org/bukkit/GameEvent.java +index cb5f7dfcdbbb548d93ad21c215ba35a9e142a7b2..e2c632afdf555418dd1dc6ad6c5d197670e2211a 100644 +--- a/src/main/java/org/bukkit/GameEvent.java ++++ b/src/main/java/org/bukkit/GameEvent.java +@@ -141,4 +141,22 @@ public abstract class GameEvent implements Keyed { + private static GameEvent getEvent(@NotNull String key) { + return Registry.GAME_EVENT.getOrThrow(NamespacedKey.minecraft(key)); + } ++ // Paper start ++ /** ++ * Gets the range of the event which is used to ++ * notify listeners of the event. ++ * ++ * @return the range ++ */ ++ public abstract int getRange(); ++ ++ /** ++ * Gets the vibration level of the game event for vibration listeners. ++ * Not all events have vibration levels, and a level of 0 means ++ * it won't cause any vibrations. ++ * ++ * @return the vibration level ++ */ ++ public abstract int getVibrationLevel(); ++ // Paper end + } +diff --git a/src/main/java/org/bukkit/inventory/ItemType.java b/src/main/java/org/bukkit/inventory/ItemType.java +index c42cfa76ff73a3ce8a164cb94a9c3f553b005ea5..15d68c4997f739c39675ef8ffa5ab7967dac59f2 100644 +--- a/src/main/java/org/bukkit/inventory/ItemType.java ++++ b/src/main/java/org/bukkit/inventory/ItemType.java +@@ -46,7 +46,7 @@ import org.jetbrains.annotations.Nullable; + * official replacement for the aforementioned enum. Entirely incompatible + * changes may occur. Do not use this API in plugins. + */ [email protected] // Paper - already required for registry builders + public interface ItemType extends Keyed, Translatable, net.kyori.adventure.translation.Translatable { // Paper - add Translatable + + /** |