aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/api/0472-Introduce-registry-entry-and-builders.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/api/0472-Introduce-registry-entry-and-builders.patch')
-rw-r--r--patches/api/0472-Introduce-registry-entry-and-builders.patch501
1 files changed, 501 insertions, 0 deletions
diff --git a/patches/api/0472-Introduce-registry-entry-and-builders.patch b/patches/api/0472-Introduce-registry-entry-and-builders.patch
new file mode 100644
index 0000000000..5d06fe4974
--- /dev/null
+++ b/patches/api/0472-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 7a1a0aebbfdaac6b6af41236d4a00512244b58fa..ef3a30d5cca29c7a7c546791be3c333e63e425f4 100644
+--- a/src/main/java/org/bukkit/inventory/ItemType.java
++++ b/src/main/java/org/bukkit/inventory/ItemType.java
+@@ -47,7 +47,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
+
+ /**