mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-30 16:19:03 +01:00
Enchantment and GameEvent Registry builders (#10889)
Co-authored-by: Bjarne Koll <git@lynxplay.dev>
This commit is contained in:
parent
2e8cf94dd1
commit
bb6b0b4cb1
3 changed files with 983 additions and 12 deletions
494
patches/api/Introduce-registry-entry-and-builders.patch
Normal file
494
patches/api/Introduce-registry-entry-and-builders.patch
Normal file
|
@ -0,0 +1,494 @@
|
||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bjarne Koll <git@lynxplay.dev>
|
||||||
|
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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- a/src/main/java/io/papermc/paper/registry/RegistryKey.java
|
||||||
|
+++ b/src/main/java/io/papermc/paper/registry/RegistryKey.java
|
||||||
|
@@ -0,0 +0,0 @@ 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");
|
||||||
|
|
||||||
|
|
||||||
|
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..0000000000000000000000000000000000000000
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/main/java/io/papermc/paper/registry/data/EnchantmentRegistryEntry.java
|
||||||
|
@@ -0,0 +0,0 @@
|
||||||
|
+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.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
+import org.jetbrains.annotations.ApiStatus;
|
||||||
|
+import org.jetbrains.annotations.Contract;
|
||||||
|
+import org.jetbrains.annotations.NotNull;
|
||||||
|
+import org.jetbrains.annotations.Range;
|
||||||
|
+import org.jetbrains.annotations.Unmodifiable;
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * A data-centric version-specific registry entry for the {@link Enchantment} type.
|
||||||
|
+ */
|
||||||
|
+@ApiStatus.Experimental
|
||||||
|
+@ApiStatus.NonExtendable
|
||||||
|
+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.
|
||||||
|
+ */
|
||||||
|
+ @NonNull Component description();
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * Provides the registry key set referencing the items this enchantment is supported on.
|
||||||
|
+ *
|
||||||
|
+ * @return the registry key set.
|
||||||
|
+ */
|
||||||
|
+ @NonNull 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 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 tag key.
|
||||||
|
+ */
|
||||||
|
+ @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.
|
||||||
|
+ */
|
||||||
|
+ @NonNull 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.
|
||||||
|
+ */
|
||||||
|
+ @NonNull 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()
|
||||||
|
+ */
|
||||||
|
+ @NonNull @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.
|
||||||
|
+ */
|
||||||
|
+ @NonNull RegistryKeySet<Enchantment> exclusiveWith();
|
||||||
|
+
|
||||||
|
+ /**
|
||||||
|
+ * 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 #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")
|
||||||
|
+ @NonNull Builder description(@NonNull 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 tag key 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")
|
||||||
|
+ @NonNull Builder supportedItems(@NonNull 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 tag key 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")
|
||||||
|
+ @NonNull 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")
|
||||||
|
+ @NonNull 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")
|
||||||
|
+ @NonNull 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")
|
||||||
|
+ @NonNull Builder minimumCost(@NotNull 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")
|
||||||
|
+ @NonNull Builder maximumCost(@NotNull 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")
|
||||||
|
+ @NonNull 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 @NonNull Builder activeSlots(final @NonNull EquipmentSlotGroup @NonNull... 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")
|
||||||
|
+ @NonNull Builder activeSlots(@NonNull Iterable<@NonNull 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")
|
||||||
|
+ @NonNull Builder exclusiveWith(@NonNull 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..0000000000000000000000000000000000000000
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/main/java/io/papermc/paper/registry/data/GameEventRegistryEntry.java
|
||||||
|
@@ -0,0 +0,0 @@
|
||||||
|
+package io.papermc.paper.registry.data;
|
||||||
|
+
|
||||||
|
+import io.papermc.paper.registry.RegistryBuilder;
|
||||||
|
+import org.bukkit.GameEvent;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
+import org.jetbrains.annotations.Contract;
|
||||||
|
+import org.jetbrains.annotations.Range;
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * A data-centric version-specific registry entry for the {@link GameEvent} type.
|
||||||
|
+ */
|
||||||
|
+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>
|
||||||
|
+ */
|
||||||
|
+ 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")
|
||||||
|
+ @NonNull 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..0000000000000000000000000000000000000000
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/main/java/io/papermc/paper/registry/data/package-info.java
|
||||||
|
@@ -0,0 +0,0 @@
|
||||||
|
+/**
|
||||||
|
+ * 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- a/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java
|
||||||
|
+++ b/src/main/java/io/papermc/paper/registry/event/RegistryEvents.java
|
||||||
|
@@ -0,0 +0,0 @@
|
||||||
|
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 static io.papermc.paper.registry.event.RegistryEventProviderImpl.create;
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* Holds providers for {@link RegistryEntryAddEvent} and {@link RegistryFreezeEvent}
|
||||||
|
* handlers for each applicable registry.
|
||||||
|
@@ -0,0 +0,0 @@ import org.jetbrains.annotations.ApiStatus;
|
||||||
|
@ApiStatus.Experimental
|
||||||
|
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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- a/src/main/java/org/bukkit/GameEvent.java
|
||||||
|
+++ b/src/main/java/org/bukkit/GameEvent.java
|
||||||
|
@@ -0,0 +0,0 @@ public abstract class GameEvent implements Keyed {
|
||||||
|
|
||||||
|
return gameEvent;
|
||||||
|
}
|
||||||
|
+ // 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- a/src/main/java/org/bukkit/inventory/ItemType.java
|
||||||
|
+++ b/src/main/java/org/bukkit/inventory/ItemType.java
|
||||||
|
@@ -0,0 +0,0 @@ import org.jetbrains.annotations.Nullable;
|
||||||
|
* official replacement for the aforementioned enum. Entirely incompatible
|
||||||
|
* changes may occur. Do not use this API in plugins.
|
||||||
|
*/
|
||||||
|
-@ApiStatus.Internal
|
||||||
|
+@ApiStatus.Experimental // Paper - already required for registry builders
|
||||||
|
public interface ItemType extends Keyed, Translatable, net.kyori.adventure.translation.Translatable { // Paper - add Translatable
|
||||||
|
|
||||||
|
/**
|
483
patches/server/Add-registry-entry-and-builders.patch
Normal file
483
patches/server/Add-registry-entry-and-builders.patch
Normal file
|
@ -0,0 +1,483 @@
|
||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bjarne Koll <git@lynxplay.dev>
|
||||||
|
Date: Thu, 13 Jun 2024 23:45:32 +0200
|
||||||
|
Subject: [PATCH] Add registry entry and builders
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistries.java b/src/main/java/io/papermc/paper/registry/PaperRegistries.java
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- a/src/main/java/io/papermc/paper/registry/PaperRegistries.java
|
||||||
|
+++ b/src/main/java/io/papermc/paper/registry/PaperRegistries.java
|
||||||
|
@@ -0,0 +0,0 @@
|
||||||
|
package io.papermc.paper.registry;
|
||||||
|
|
||||||
|
import io.papermc.paper.adventure.PaperAdventure;
|
||||||
|
+import io.papermc.paper.registry.data.PaperEnchantmentRegistryEntry;
|
||||||
|
+import io.papermc.paper.registry.data.PaperGameEventRegistryEntry;
|
||||||
|
import io.papermc.paper.registry.entry.RegistryEntry;
|
||||||
|
import io.papermc.paper.registry.tag.TagKey;
|
||||||
|
import java.util.Collections;
|
||||||
|
@@ -0,0 +0,0 @@ public final class PaperRegistries {
|
||||||
|
static {
|
||||||
|
REGISTRY_ENTRIES = List.of(
|
||||||
|
// built-ins
|
||||||
|
- entry(Registries.GAME_EVENT, RegistryKey.GAME_EVENT, GameEvent.class, CraftGameEvent::new),
|
||||||
|
+ writable(Registries.GAME_EVENT, RegistryKey.GAME_EVENT, GameEvent.class, CraftGameEvent::new, PaperGameEventRegistryEntry.PaperBuilder::new),
|
||||||
|
entry(Registries.INSTRUMENT, RegistryKey.INSTRUMENT, MusicInstrument.class, CraftMusicInstrument::new),
|
||||||
|
entry(Registries.MOB_EFFECT, RegistryKey.MOB_EFFECT, PotionEffectType.class, CraftPotionEffectType::new),
|
||||||
|
entry(Registries.STRUCTURE_TYPE, RegistryKey.STRUCTURE_TYPE, StructureType.class, CraftStructureType::new),
|
||||||
|
@@ -0,0 +0,0 @@ public final class PaperRegistries {
|
||||||
|
entry(Registries.TRIM_PATTERN, RegistryKey.TRIM_PATTERN, TrimPattern.class, CraftTrimPattern::new).delayed(),
|
||||||
|
entry(Registries.DAMAGE_TYPE, RegistryKey.DAMAGE_TYPE, DamageType.class, CraftDamageType::new).delayed(),
|
||||||
|
entry(Registries.WOLF_VARIANT, RegistryKey.WOLF_VARIANT, Wolf.Variant.class, CraftWolf.CraftVariant::new).delayed(),
|
||||||
|
- entry(Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT, Enchantment.class, CraftEnchantment::new).withSerializationUpdater(FieldRename.ENCHANTMENT_RENAME).delayed(),
|
||||||
|
+ writable(Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT, Enchantment.class, CraftEnchantment::new, PaperEnchantmentRegistryEntry.PaperBuilder::new).withSerializationUpdater(FieldRename.ENCHANTMENT_RENAME).delayed(),
|
||||||
|
entry(Registries.JUKEBOX_SONG, RegistryKey.JUKEBOX_SONG, JukeboxSong.class, CraftJukeboxSong::new).delayed(),
|
||||||
|
|
||||||
|
// api-only
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/registry/data/PaperEnchantmentRegistryEntry.java b/src/main/java/io/papermc/paper/registry/data/PaperEnchantmentRegistryEntry.java
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/main/java/io/papermc/paper/registry/data/PaperEnchantmentRegistryEntry.java
|
||||||
|
@@ -0,0 +0,0 @@
|
||||||
|
+package io.papermc.paper.registry.data;
|
||||||
|
+
|
||||||
|
+import com.google.common.base.Preconditions;
|
||||||
|
+import com.google.common.collect.Iterables;
|
||||||
|
+import com.google.common.collect.Lists;
|
||||||
|
+import io.papermc.paper.registry.PaperRegistryBuilder;
|
||||||
|
+import io.papermc.paper.registry.RegistryKey;
|
||||||
|
+import io.papermc.paper.registry.TypedKey;
|
||||||
|
+import io.papermc.paper.registry.data.util.Checks;
|
||||||
|
+import io.papermc.paper.registry.data.util.Conversions;
|
||||||
|
+import io.papermc.paper.registry.set.PaperRegistrySets;
|
||||||
|
+import io.papermc.paper.registry.set.RegistryKeySet;
|
||||||
|
+import java.util.Collections;
|
||||||
|
+import java.util.List;
|
||||||
|
+import java.util.Optional;
|
||||||
|
+import java.util.OptionalInt;
|
||||||
|
+import net.minecraft.core.HolderSet;
|
||||||
|
+import net.minecraft.core.component.DataComponentMap;
|
||||||
|
+import net.minecraft.core.registries.Registries;
|
||||||
|
+import net.minecraft.network.chat.Component;
|
||||||
|
+import net.minecraft.world.entity.EquipmentSlotGroup;
|
||||||
|
+import net.minecraft.world.item.Item;
|
||||||
|
+import net.minecraft.world.item.enchantment.Enchantment;
|
||||||
|
+import org.bukkit.craftbukkit.CraftEquipmentSlot;
|
||||||
|
+import org.bukkit.inventory.ItemType;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||||
|
+import org.jetbrains.annotations.Range;
|
||||||
|
+
|
||||||
|
+import static io.papermc.paper.registry.data.util.Checks.asArgument;
|
||||||
|
+import static io.papermc.paper.registry.data.util.Checks.asArgumentMin;
|
||||||
|
+import static io.papermc.paper.registry.data.util.Checks.asConfigured;
|
||||||
|
+
|
||||||
|
+@DefaultQualifier(NonNull.class)
|
||||||
|
+public class PaperEnchantmentRegistryEntry implements EnchantmentRegistryEntry {
|
||||||
|
+
|
||||||
|
+ // Top level
|
||||||
|
+ protected @MonotonicNonNull Component description;
|
||||||
|
+
|
||||||
|
+ // Definition
|
||||||
|
+ protected @MonotonicNonNull HolderSet<Item> supportedItems;
|
||||||
|
+ protected @Nullable HolderSet<Item> primaryItems;
|
||||||
|
+ protected OptionalInt weight = OptionalInt.empty();
|
||||||
|
+ protected OptionalInt maxLevel = OptionalInt.empty();
|
||||||
|
+ protected Enchantment.@MonotonicNonNull Cost minimumCost;
|
||||||
|
+ protected Enchantment.@MonotonicNonNull Cost maximumCost;
|
||||||
|
+ protected OptionalInt anvilCost = OptionalInt.empty();
|
||||||
|
+ protected @MonotonicNonNull List<EquipmentSlotGroup> activeSlots;
|
||||||
|
+
|
||||||
|
+ // Exclusive
|
||||||
|
+ protected HolderSet<Enchantment> exclusiveWith = HolderSet.empty(); // Paper added default to empty.
|
||||||
|
+
|
||||||
|
+ // Effects
|
||||||
|
+ protected final DataComponentMap effects;
|
||||||
|
+
|
||||||
|
+ protected final Conversions conversions;
|
||||||
|
+
|
||||||
|
+ public PaperEnchantmentRegistryEntry(
|
||||||
|
+ final Conversions conversions,
|
||||||
|
+ final TypedKey<org.bukkit.enchantments.Enchantment> ignoredKey,
|
||||||
|
+ final @Nullable Enchantment internal
|
||||||
|
+ ) {
|
||||||
|
+ this.conversions = conversions;
|
||||||
|
+ if (internal == null) {
|
||||||
|
+ this.effects = DataComponentMap.EMPTY;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // top level
|
||||||
|
+ this.description = internal.description();
|
||||||
|
+
|
||||||
|
+ // definition
|
||||||
|
+ final Enchantment.EnchantmentDefinition definition = internal.definition();
|
||||||
|
+ this.supportedItems = definition.supportedItems();
|
||||||
|
+ this.primaryItems = definition.primaryItems().orElse(null);
|
||||||
|
+ this.weight = OptionalInt.of(definition.weight());
|
||||||
|
+ this.maxLevel = OptionalInt.of(definition.maxLevel());
|
||||||
|
+ this.minimumCost = definition.minCost();
|
||||||
|
+ this.maximumCost = definition.maxCost();
|
||||||
|
+ this.anvilCost = OptionalInt.of(definition.anvilCost());
|
||||||
|
+ this.activeSlots = definition.slots();
|
||||||
|
+
|
||||||
|
+ // exclusive
|
||||||
|
+ this.exclusiveWith = internal.exclusiveSet();
|
||||||
|
+
|
||||||
|
+ // effects
|
||||||
|
+ this.effects = internal.effects();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public net.kyori.adventure.text.Component description() {
|
||||||
|
+ return this.conversions.asAdventure(asConfigured(this.description, "description"));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public RegistryKeySet<ItemType> supportedItems() {
|
||||||
|
+ return PaperRegistrySets.convertToApi(RegistryKey.ITEM, asConfigured(this.supportedItems, "supportedItems"));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public @Nullable RegistryKeySet<ItemType> primaryItems() {
|
||||||
|
+ return this.primaryItems == null ? null : PaperRegistrySets.convertToApi(RegistryKey.ITEM, this.primaryItems);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public @Range(from = 1, to = 1024) int weight() {
|
||||||
|
+ return asConfigured(this.weight, "weight");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public @Range(from = 1, to = 255) int maxLevel() {
|
||||||
|
+ return asConfigured(this.maxLevel, "maxLevel");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public EnchantmentCost minimumCost() {
|
||||||
|
+ final Enchantment.@MonotonicNonNull Cost cost = asConfigured(this.minimumCost, "minimumCost");
|
||||||
|
+ return EnchantmentRegistryEntry.EnchantmentCost.of(cost.base(), cost.perLevelAboveFirst());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public EnchantmentCost maximumCost() {
|
||||||
|
+ final Enchantment.@MonotonicNonNull Cost cost = asConfigured(this.maximumCost, "maximumCost");
|
||||||
|
+ return EnchantmentRegistryEntry.EnchantmentCost.of(cost.base(), cost.perLevelAboveFirst());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public @Range(from = 0, to = Integer.MAX_VALUE) int anvilCost() {
|
||||||
|
+ return asConfigured(this.anvilCost, "anvilCost");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public List<org.bukkit.inventory.EquipmentSlotGroup> activeSlots() {
|
||||||
|
+ return Collections.unmodifiableList(Lists.transform(asConfigured(this.activeSlots, "activeSlots"), CraftEquipmentSlot::getSlot));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public RegistryKeySet<org.bukkit.enchantments.Enchantment> exclusiveWith() {
|
||||||
|
+ return PaperRegistrySets.convertToApi(RegistryKey.ENCHANTMENT, this.exclusiveWith);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static final class PaperBuilder extends PaperEnchantmentRegistryEntry implements EnchantmentRegistryEntry.Builder,
|
||||||
|
+ PaperRegistryBuilder<Enchantment, org.bukkit.enchantments.Enchantment> {
|
||||||
|
+
|
||||||
|
+ public PaperBuilder(final Conversions conversions, final TypedKey<org.bukkit.enchantments.Enchantment> key, final @Nullable Enchantment internal) {
|
||||||
|
+ super(conversions, key, internal);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Builder description(final net.kyori.adventure.text.Component description) {
|
||||||
|
+ this.description = this.conversions.asVanilla(asArgument(description, "description"));
|
||||||
|
+ return this;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Builder supportedItems(final RegistryKeySet<ItemType> supportedItems) {
|
||||||
|
+ this.supportedItems = PaperRegistrySets.convertToNms(Registries.ITEM, this.conversions.lookup(), asArgument(supportedItems, "supportedItems"));
|
||||||
|
+ return this;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Builder primaryItems(final @Nullable RegistryKeySet<ItemType> primaryItems) {
|
||||||
|
+ this.primaryItems = primaryItems == null ? null : PaperRegistrySets.convertToNms(Registries.ITEM, this.conversions.lookup(), primaryItems);
|
||||||
|
+ return this;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Builder weight(final @Range(from = 1, to = 1024) int weight) {
|
||||||
|
+ this.weight = OptionalInt.of(Checks.asArgumentRange(weight, "weight", 1, 1024));
|
||||||
|
+ return this;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Builder maxLevel(final @Range(from = 1, to = 255) int maxLevel) {
|
||||||
|
+ this.maxLevel = OptionalInt.of(Checks.asArgumentRange(maxLevel, "maxLevel", 1, 255));
|
||||||
|
+ return this;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Builder minimumCost(final EnchantmentCost minimumCost) {
|
||||||
|
+ final EnchantmentCost validCost = asArgument(minimumCost, "minimumCost");
|
||||||
|
+ this.minimumCost = Enchantment.dynamicCost(validCost.baseCost(), validCost.additionalPerLevelCost());
|
||||||
|
+ return this;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Builder maximumCost(final EnchantmentCost maximumCost) {
|
||||||
|
+ final EnchantmentCost validCost = asArgument(maximumCost, "maximumCost");
|
||||||
|
+ this.maximumCost = Enchantment.dynamicCost(validCost.baseCost(), validCost.additionalPerLevelCost());
|
||||||
|
+ return this;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Builder anvilCost(final @Range(from = 0, to = Integer.MAX_VALUE) int anvilCost) {
|
||||||
|
+ Preconditions.checkArgument(anvilCost >= 0, "anvilCost must be non-negative");
|
||||||
|
+ this.anvilCost = OptionalInt.of(asArgumentMin(anvilCost, "anvilCost", 0));
|
||||||
|
+ return this;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Builder activeSlots(final Iterable<org.bukkit.inventory.EquipmentSlotGroup> activeSlots) {
|
||||||
|
+ this.activeSlots = Lists.newArrayList(Iterables.transform(asArgument(activeSlots, "activeSlots"), CraftEquipmentSlot::getNMSGroup));
|
||||||
|
+ return this;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Builder exclusiveWith(final RegistryKeySet<org.bukkit.enchantments.Enchantment> exclusiveWith) {
|
||||||
|
+ this.exclusiveWith = PaperRegistrySets.convertToNms(Registries.ENCHANTMENT, this.conversions.lookup(), asArgument(exclusiveWith, "exclusiveWith"));
|
||||||
|
+ return this;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public Enchantment build() {
|
||||||
|
+ final Enchantment.EnchantmentDefinition def = new Enchantment.EnchantmentDefinition(
|
||||||
|
+ asConfigured(this.supportedItems, "supportedItems"),
|
||||||
|
+ Optional.ofNullable(this.primaryItems),
|
||||||
|
+ this.weight(),
|
||||||
|
+ this.maxLevel(),
|
||||||
|
+ asConfigured(this.minimumCost, "minimumCost"),
|
||||||
|
+ asConfigured(this.maximumCost, "maximumCost"),
|
||||||
|
+ this.anvilCost(),
|
||||||
|
+ Collections.unmodifiableList(asConfigured(this.activeSlots, "activeSlots"))
|
||||||
|
+ );
|
||||||
|
+ return new Enchantment(
|
||||||
|
+ asConfigured(this.description, "description"),
|
||||||
|
+ def,
|
||||||
|
+ this.exclusiveWith,
|
||||||
|
+ this.effects
|
||||||
|
+ );
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/registry/data/PaperGameEventRegistryEntry.java b/src/main/java/io/papermc/paper/registry/data/PaperGameEventRegistryEntry.java
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/main/java/io/papermc/paper/registry/data/PaperGameEventRegistryEntry.java
|
||||||
|
@@ -0,0 +0,0 @@
|
||||||
|
+package io.papermc.paper.registry.data;
|
||||||
|
+
|
||||||
|
+import io.papermc.paper.registry.PaperRegistryBuilder;
|
||||||
|
+import io.papermc.paper.registry.data.util.Conversions;
|
||||||
|
+import java.util.OptionalInt;
|
||||||
|
+import net.minecraft.world.level.gameevent.GameEvent;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||||
|
+import org.jetbrains.annotations.Range;
|
||||||
|
+
|
||||||
|
+import static io.papermc.paper.registry.data.util.Checks.asArgumentMin;
|
||||||
|
+import static io.papermc.paper.registry.data.util.Checks.asConfigured;
|
||||||
|
+
|
||||||
|
+@DefaultQualifier(NonNull.class)
|
||||||
|
+public class PaperGameEventRegistryEntry implements GameEventRegistryEntry {
|
||||||
|
+
|
||||||
|
+ protected OptionalInt range = OptionalInt.empty();
|
||||||
|
+
|
||||||
|
+ public PaperGameEventRegistryEntry(
|
||||||
|
+ final Conversions ignoredConversions,
|
||||||
|
+ final io.papermc.paper.registry.TypedKey<org.bukkit.GameEvent> ignoredKey,
|
||||||
|
+ final @Nullable GameEvent nms
|
||||||
|
+ ) {
|
||||||
|
+ if (nms == null) return;
|
||||||
|
+
|
||||||
|
+ this.range = OptionalInt.of(nms.notificationRadius());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public @Range(from = 0, to = Integer.MAX_VALUE) int range() {
|
||||||
|
+ return asConfigured(this.range, "range");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static final class PaperBuilder extends PaperGameEventRegistryEntry implements GameEventRegistryEntry.Builder,
|
||||||
|
+ PaperRegistryBuilder<GameEvent, org.bukkit.GameEvent> {
|
||||||
|
+
|
||||||
|
+ public PaperBuilder(
|
||||||
|
+ final Conversions conversions,
|
||||||
|
+ final io.papermc.paper.registry.TypedKey<org.bukkit.GameEvent> key,
|
||||||
|
+ final @Nullable GameEvent nms
|
||||||
|
+ ) {
|
||||||
|
+ super(conversions, key, nms);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public GameEventRegistryEntry.Builder range(final @Range(from = 0, to = Integer.MAX_VALUE) int range) {
|
||||||
|
+ this.range = OptionalInt.of(asArgumentMin(range, "range", 0));
|
||||||
|
+ return this;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public GameEvent build() {
|
||||||
|
+ return new GameEvent(this.range());
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
diff --git a/src/main/java/io/papermc/paper/registry/data/util/Checks.java b/src/main/java/io/papermc/paper/registry/data/util/Checks.java
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/main/java/io/papermc/paper/registry/data/util/Checks.java
|
||||||
|
@@ -0,0 +0,0 @@
|
||||||
|
+package io.papermc.paper.registry.data.util;
|
||||||
|
+
|
||||||
|
+import java.util.OptionalInt;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||||
|
+
|
||||||
|
+@DefaultQualifier(NonNull.class)
|
||||||
|
+public final class Checks {
|
||||||
|
+
|
||||||
|
+ public static <T> T asConfigured(final @Nullable T value, final String field) {
|
||||||
|
+ if (value == null) {
|
||||||
|
+ throw new IllegalStateException(field + " has not been configured");
|
||||||
|
+ }
|
||||||
|
+ return value;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static int asConfigured(final OptionalInt value, final String field) {
|
||||||
|
+ if (value.isEmpty()) {
|
||||||
|
+ throw new IllegalStateException(field + " has not been configured");
|
||||||
|
+ }
|
||||||
|
+ return value.getAsInt();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static <T> T asArgument(final @Nullable T value, final String field) {
|
||||||
|
+ if (value == null) {
|
||||||
|
+ throw new IllegalArgumentException("argument " + value + " cannot be null");
|
||||||
|
+ }
|
||||||
|
+ return value;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static int asArgumentRange(final int value, final String field, final int min, final int max) {
|
||||||
|
+ if (value < min || value > max) {
|
||||||
|
+ throw new IllegalArgumentException("argument " + field + " must be [" + min + ", " + max + "]");
|
||||||
|
+ }
|
||||||
|
+ return value;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public static int asArgumentMin(final int value, final String field, final int min) {
|
||||||
|
+ if (value < min) {
|
||||||
|
+ throw new IllegalArgumentException("argument " + field + " must be [" + min + ",+inf)");
|
||||||
|
+ }
|
||||||
|
+ return value;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private Checks() {
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
diff --git a/src/main/java/net/minecraft/world/level/gameevent/GameEvent.java b/src/main/java/net/minecraft/world/level/gameevent/GameEvent.java
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- a/src/main/java/net/minecraft/world/level/gameevent/GameEvent.java
|
||||||
|
+++ b/src/main/java/net/minecraft/world/level/gameevent/GameEvent.java
|
||||||
|
@@ -0,0 +0,0 @@ public record GameEvent(int notificationRadius) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Holder.Reference<GameEvent> register(String id, int range) {
|
||||||
|
- return Registry.registerForHolder(BuiltInRegistries.GAME_EVENT, ResourceLocation.withDefaultNamespace(id), new GameEvent(range));
|
||||||
|
+ return io.papermc.paper.registry.PaperRegistryListenerManager.INSTANCE.registerForHolderWithListeners(BuiltInRegistries.GAME_EVENT, ResourceLocation.withDefaultNamespace(id), new GameEvent(range)); // Paper - run with listeners
|
||||||
|
}
|
||||||
|
|
||||||
|
public static record Context(@Nullable Entity sourceEntity, @Nullable BlockState affectedState) {
|
||||||
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftGameEvent.java b/src/main/java/org/bukkit/craftbukkit/CraftGameEvent.java
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftGameEvent.java
|
||||||
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftGameEvent.java
|
||||||
|
@@ -0,0 +0,0 @@ public class CraftGameEvent extends GameEvent implements Handleable<net.minecraf
|
||||||
|
}
|
||||||
|
|
||||||
|
private final NamespacedKey key;
|
||||||
|
+ private final net.minecraft.resources.ResourceKey<net.minecraft.world.level.gameevent.GameEvent> handleKey; // Paper
|
||||||
|
private final net.minecraft.world.level.gameevent.GameEvent handle;
|
||||||
|
|
||||||
|
public CraftGameEvent(NamespacedKey key, net.minecraft.world.level.gameevent.GameEvent handle) {
|
||||||
|
this.key = key;
|
||||||
|
+ this.handleKey = net.minecraft.resources.ResourceKey.create(net.minecraft.core.registries.Registries.GAME_EVENT, org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(key)); // Paper
|
||||||
|
this.handle = handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +0,0 @@ public class CraftGameEvent extends GameEvent implements Handleable<net.minecraf
|
||||||
|
return this.handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Paper start
|
||||||
|
+ @Override
|
||||||
|
+ public int getRange() {
|
||||||
|
+ return this.handle.notificationRadius();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ @Override
|
||||||
|
+ public int getVibrationLevel() {
|
||||||
|
+ return net.minecraft.world.level.gameevent.vibrations.VibrationSystem.getGameEventFrequency(this.handleKey);
|
||||||
|
+ }
|
||||||
|
+ // Paper end
|
||||||
|
+
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public NamespacedKey getKey() {
|
||||||
|
diff --git a/src/test/java/io/papermc/paper/registry/RegistryBuilderTest.java b/src/test/java/io/papermc/paper/registry/RegistryBuilderTest.java
|
||||||
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||||
|
--- a/src/test/java/io/papermc/paper/registry/RegistryBuilderTest.java
|
||||||
|
+++ b/src/test/java/io/papermc/paper/registry/RegistryBuilderTest.java
|
||||||
|
@@ -0,0 +0,0 @@
|
||||||
|
package io.papermc.paper.registry;
|
||||||
|
|
||||||
|
+import io.papermc.paper.registry.data.PaperEnchantmentRegistryEntry;
|
||||||
|
+import io.papermc.paper.registry.data.PaperGameEventRegistryEntry;
|
||||||
|
import io.papermc.paper.registry.data.util.Conversions;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
+import net.minecraft.core.registries.Registries;
|
||||||
|
import net.minecraft.resources.RegistryOps;
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
+import net.minecraft.world.item.enchantment.Enchantment;
|
||||||
|
+import net.minecraft.world.level.gameevent.GameEvent;
|
||||||
|
import org.bukkit.support.AbstractTestingBase;
|
||||||
|
-import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
+import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||||
|
|
||||||
|
class RegistryBuilderTest extends AbstractTestingBase {
|
||||||
|
|
||||||
|
static List<Arguments> registries() {
|
||||||
|
return List.of(
|
||||||
|
+ arguments(Registries.ENCHANTMENT, (PaperRegistryBuilder.Filler<Enchantment, org.bukkit.enchantments.Enchantment, PaperEnchantmentRegistryEntry.PaperBuilder>) PaperEnchantmentRegistryEntry.PaperBuilder::new),
|
||||||
|
+ arguments(Registries.GAME_EVENT, (PaperRegistryBuilder.Filler<GameEvent, org.bukkit.GameEvent, PaperGameEventRegistryEntry.PaperBuilder>) PaperGameEventRegistryEntry.PaperBuilder::new)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
- @Disabled
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("registries")
|
||||||
|
<M, T> void testEquality(final ResourceKey<? extends Registry<M>> resourceKey, final PaperRegistryBuilder.Filler<M, T, ?> filler) {
|
|
@ -82,7 +82,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||||
+ @FunctionalInterface
|
+ @FunctionalInterface
|
||||||
+ interface Filler<M, T, B extends PaperRegistryBuilder<M, T>> {
|
+ interface Filler<M, T, B extends PaperRegistryBuilder<M, T>> {
|
||||||
+
|
+
|
||||||
+ B fill(@Nullable Conversions conversions, TypedKey<T> key, @Nullable M nms);
|
+ B fill(Conversions conversions, TypedKey<T> key, @Nullable M nms);
|
||||||
+
|
+
|
||||||
+ default Factory<M, T, B> asFactory() {
|
+ default Factory<M, T, B> asFactory() {
|
||||||
+ return (lookup, key) -> this.fill(lookup, key, null);
|
+ return (lookup, key) -> this.fill(lookup, key, null);
|
||||||
|
@ -92,7 +92,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||||
+ @FunctionalInterface
|
+ @FunctionalInterface
|
||||||
+ interface Factory<M, T, B extends PaperRegistryBuilder<M, T>> {
|
+ interface Factory<M, T, B extends PaperRegistryBuilder<M, T>> {
|
||||||
+
|
+
|
||||||
+ B create(@Nullable Conversions conversions, TypedKey<T> key);
|
+ B create(Conversions conversions, TypedKey<T> key);
|
||||||
+ }
|
+ }
|
||||||
+}
|
+}
|
||||||
diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistryListenerManager.java b/src/main/java/io/papermc/paper/registry/PaperRegistryListenerManager.java
|
diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistryListenerManager.java b/src/main/java/io/papermc/paper/registry/PaperRegistryListenerManager.java
|
||||||
|
@ -441,11 +441,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||||
+import java.util.function.BiFunction;
|
+import java.util.function.BiFunction;
|
||||||
+import net.minecraft.core.MappedRegistry;
|
+import net.minecraft.core.MappedRegistry;
|
||||||
+import net.minecraft.core.Registry;
|
+import net.minecraft.core.Registry;
|
||||||
+import net.minecraft.resources.RegistryOps;
|
|
||||||
+import net.minecraft.resources.ResourceKey;
|
+import net.minecraft.resources.ResourceKey;
|
||||||
+import org.bukkit.Keyed;
|
+import org.bukkit.Keyed;
|
||||||
+import org.bukkit.NamespacedKey;
|
+import org.bukkit.NamespacedKey;
|
||||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
|
||||||
+
|
+
|
||||||
+public class AddableRegistryEntry<M, T extends Keyed, B extends PaperRegistryBuilder<M, T>> extends CraftRegistryEntry<M, T> implements RegistryEntry.Addable<M, T, B> {
|
+public class AddableRegistryEntry<M, T extends Keyed, B extends PaperRegistryBuilder<M, T>> extends CraftRegistryEntry<M, T> implements RegistryEntry.Addable<M, T, B> {
|
||||||
+
|
+
|
||||||
|
@ -472,7 +470,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ @Override
|
+ @Override
|
||||||
+ public B fillBuilder(final @Nullable Conversions conversions, final TypedKey<T> key, final M nms) {
|
+ public B fillBuilder(final Conversions conversions, final TypedKey<T> key, final M nms) {
|
||||||
+ return this.builderFiller.fill(conversions, key, nms);
|
+ return this.builderFiller.fill(conversions, key, nms);
|
||||||
+ }
|
+ }
|
||||||
+}
|
+}
|
||||||
|
@ -493,7 +491,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||||
+import net.minecraft.resources.ResourceKey;
|
+import net.minecraft.resources.ResourceKey;
|
||||||
+import org.bukkit.Keyed;
|
+import org.bukkit.Keyed;
|
||||||
+import org.bukkit.NamespacedKey;
|
+import org.bukkit.NamespacedKey;
|
||||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
|
||||||
+
|
+
|
||||||
+public class ModifiableRegistryEntry<M, T extends Keyed, B extends PaperRegistryBuilder<M, T>> extends CraftRegistryEntry<M, T> implements RegistryEntry.Modifiable<M, T, B> {
|
+public class ModifiableRegistryEntry<M, T extends Keyed, B extends PaperRegistryBuilder<M, T>> extends CraftRegistryEntry<M, T> implements RegistryEntry.Modifiable<M, T, B> {
|
||||||
+
|
+
|
||||||
|
@ -511,7 +508,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ @Override
|
+ @Override
|
||||||
+ public B fillBuilder(final @Nullable Conversions conversions, final TypedKey<T> key, final M nms) {
|
+ public B fillBuilder(final Conversions conversions, final TypedKey<T> key, final M nms) {
|
||||||
+ return this.builderFiller.fill(conversions, key, nms);
|
+ return this.builderFiller.fill(conversions, key, nms);
|
||||||
+ }
|
+ }
|
||||||
+}
|
+}
|
||||||
|
@ -533,10 +530,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||||
import io.papermc.paper.registry.legacy.DelayedRegistryEntry;
|
import io.papermc.paper.registry.legacy.DelayedRegistryEntry;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import net.minecraft.core.Registry;
|
@@ -0,0 +0,0 @@ import org.bukkit.Keyed;
|
||||||
+import net.minecraft.resources.RegistryOps;
|
|
||||||
import net.minecraft.resources.ResourceKey;
|
|
||||||
import org.bukkit.Keyed;
|
|
||||||
import org.bukkit.NamespacedKey;
|
import org.bukkit.NamespacedKey;
|
||||||
import org.bukkit.craftbukkit.util.ApiVersion;
|
import org.bukkit.craftbukkit.util.ApiVersion;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
@ -550,7 +544,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||||
|
|
||||||
+ interface BuilderHolder<M, T, B extends PaperRegistryBuilder<M, T>> extends RegistryEntryInfo<M, T> {
|
+ interface BuilderHolder<M, T, B extends PaperRegistryBuilder<M, T>> extends RegistryEntryInfo<M, T> {
|
||||||
+
|
+
|
||||||
+ B fillBuilder(@Nullable Conversions conversions, TypedKey<T> key, M nms);
|
+ B fillBuilder(Conversions conversions, TypedKey<T> key, M nms);
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ /**
|
+ /**
|
||||||
|
|
Loading…
Reference in a new issue