diff options
Diffstat (limited to 'patches/unapplied/server/0991-Add-registry-entry-and-builders.patch')
-rw-r--r-- | patches/unapplied/server/0991-Add-registry-entry-and-builders.patch | 575 |
1 files changed, 575 insertions, 0 deletions
diff --git a/patches/unapplied/server/0991-Add-registry-entry-and-builders.patch b/patches/unapplied/server/0991-Add-registry-entry-and-builders.patch new file mode 100644 index 0000000000..36bfa68a40 --- /dev/null +++ b/patches/unapplied/server/0991-Add-registry-entry-and-builders.patch @@ -0,0 +1,575 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Bjarne Koll <[email protected]> +Date: Thu, 13 Jun 2024 23:45:32 +0200 +Subject: [PATCH] Add registry entry and builders + +Feature patch + +diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistries.java b/src/main/java/io/papermc/paper/registry/PaperRegistries.java +index 86c9f87cdb41c0d1ccc2a61b501f969cfaae47bc..fd024576e70e0c121c1477a0b7777af18159b7c4 100644 +--- a/src/main/java/io/papermc/paper/registry/PaperRegistries.java ++++ b/src/main/java/io/papermc/paper/registry/PaperRegistries.java +@@ -2,6 +2,9 @@ package io.papermc.paper.registry; + + import com.google.common.base.Preconditions; + 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.data.PaperPaintingVariantRegistryEntry; + import io.papermc.paper.registry.entry.RegistryEntry; + import io.papermc.paper.registry.tag.TagKey; + import java.util.Collections; +@@ -78,7 +81,7 @@ 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.STRUCTURE_TYPE, RegistryKey.STRUCTURE_TYPE, StructureType.class, CraftStructureType::new), + entry(Registries.MOB_EFFECT, RegistryKey.MOB_EFFECT, PotionEffectType.class, CraftPotionEffectType::new), + entry(Registries.BLOCK, RegistryKey.BLOCK, BlockType.class, CraftBlockType::new), +@@ -100,10 +103,10 @@ 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(), + entry(Registries.BANNER_PATTERN, RegistryKey.BANNER_PATTERN, PatternType.class, CraftPatternType::new).delayed(), +- entry(Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT, Art.class, CraftArt::new).delayed(), ++ writable(Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT, Art.class, CraftArt::new, PaperPaintingVariantRegistryEntry.PaperBuilder::new).delayed(), + entry(Registries.INSTRUMENT, RegistryKey.INSTRUMENT, MusicInstrument.class, CraftMusicInstrument::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..1b1c6838452d3001070a5d43cc49e3a09de7153d +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/data/PaperEnchantmentRegistryEntry.java +@@ -0,0 +1,230 @@ ++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.jetbrains.annotations.Range; ++import org.jspecify.annotations.Nullable; ++ ++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; ++ ++public class PaperEnchantmentRegistryEntry implements EnchantmentRegistryEntry { ++ ++ // Top level ++ protected @Nullable Component description; ++ ++ // Definition ++ protected @Nullable HolderSet<Item> supportedItems; ++ protected @Nullable HolderSet<Item> primaryItems; ++ protected OptionalInt weight = OptionalInt.empty(); ++ protected OptionalInt maxLevel = OptionalInt.empty(); ++ protected Enchantment.@Nullable Cost minimumCost; ++ protected Enchantment.@Nullable Cost maximumCost; ++ protected OptionalInt anvilCost = OptionalInt.empty(); ++ protected @Nullable List<EquipmentSlotGroup> activeSlots; ++ ++ // Exclusive ++ protected HolderSet<Enchantment> exclusiveWith = HolderSet.empty(); // Paper added default to empty. ++ ++ // Effects ++ protected 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.Cost cost = asConfigured(this.minimumCost, "minimumCost"); ++ return EnchantmentRegistryEntry.EnchantmentCost.of(cost.base(), cost.perLevelAboveFirst()); ++ } ++ ++ @Override ++ public EnchantmentCost maximumCost() { ++ final Enchantment.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..2100e8aca6f7ae7b90545bd3f4d4b800dba65daa +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/data/PaperGameEventRegistryEntry.java +@@ -0,0 +1,54 @@ ++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.jetbrains.annotations.Range; ++import org.jspecify.annotations.Nullable; ++ ++import static io.papermc.paper.registry.data.util.Checks.asArgumentMin; ++import static io.papermc.paper.registry.data.util.Checks.asConfigured; ++ ++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 internal ++ ) { ++ if (internal == null) return; ++ ++ this.range = OptionalInt.of(internal.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 internal ++ ) { ++ super(conversions, key, internal); ++ } ++ ++ @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/PaperPaintingVariantRegistryEntry.java b/src/main/java/io/papermc/paper/registry/data/PaperPaintingVariantRegistryEntry.java +new file mode 100644 +index 0000000000000000000000000000000000000000..68b3d747f759f615a3c942de3f4d7a0fe856cd84 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/data/PaperPaintingVariantRegistryEntry.java +@@ -0,0 +1,120 @@ ++package io.papermc.paper.registry.data; ++ ++import io.papermc.paper.adventure.PaperAdventure; ++import io.papermc.paper.registry.PaperRegistryBuilder; ++import io.papermc.paper.registry.TypedKey; ++import io.papermc.paper.registry.data.util.Conversions; ++import java.util.Optional; ++import java.util.OptionalInt; ++import net.kyori.adventure.key.Key; ++import net.minecraft.network.chat.Component; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.world.entity.decoration.PaintingVariant; ++import org.bukkit.Art; ++import org.jetbrains.annotations.Range; ++import org.jspecify.annotations.NullMarked; ++import org.jspecify.annotations.Nullable; ++ ++import static io.papermc.paper.registry.data.util.Checks.asArgument; ++import static io.papermc.paper.registry.data.util.Checks.asArgumentRange; ++import static io.papermc.paper.registry.data.util.Checks.asConfigured; ++ ++@NullMarked ++public class PaperPaintingVariantRegistryEntry implements PaintingVariantRegistryEntry { ++ ++ protected OptionalInt width = OptionalInt.empty(); ++ protected OptionalInt height = OptionalInt.empty(); ++ protected @Nullable Component title; ++ protected @Nullable Component author; ++ protected @Nullable ResourceLocation assetId; ++ ++ protected final Conversions conversions; ++ ++ public PaperPaintingVariantRegistryEntry( ++ final Conversions conversions, ++ final TypedKey<Art> ignoredKey, ++ final @Nullable PaintingVariant internal ++ ) { ++ this.conversions = conversions; ++ if (internal == null) return; ++ ++ this.width = OptionalInt.of(internal.width()); ++ this.height = OptionalInt.of(internal.height()); ++ this.title = internal.title().orElse(null); ++ this.author = internal.author().orElse(null); ++ this.assetId = internal.assetId(); ++ } ++ ++ @Override ++ public @Range(from = 1, to = 16) int width() { ++ return asConfigured(this.width, "width"); ++ } ++ ++ @Override ++ public @Range(from = 1, to = 16) int height() { ++ return asConfigured(this.height, "height"); ++ } ++ ++ @Override ++ public net.kyori.adventure.text.@Nullable Component title() { ++ return this.title == null ? null : this.conversions.asAdventure(this.title); ++ } ++ ++ @Override ++ public net.kyori.adventure.text.@Nullable Component author() { ++ return this.author == null ? null : this.conversions.asAdventure(this.author); ++ } ++ ++ @Override ++ public Key assetId() { ++ return PaperAdventure.asAdventure(asConfigured(this.assetId, "assetId")); ++ } ++ ++ public static final class PaperBuilder extends PaperPaintingVariantRegistryEntry implements PaintingVariantRegistryEntry.Builder, PaperRegistryBuilder<PaintingVariant, Art> { ++ ++ public PaperBuilder(final Conversions conversions, final TypedKey<Art> key, final @Nullable PaintingVariant internal) { ++ super(conversions, key, internal); ++ } ++ ++ @Override ++ public Builder width(final @Range(from = 1, to = 16) int width) { ++ this.width = OptionalInt.of(asArgumentRange(width, "width", 1, 16)); ++ return this; ++ } ++ ++ @Override ++ public Builder height(final @Range(from = 1, to = 16) int height) { ++ this.height = OptionalInt.of(asArgumentRange(height, "height", 1, 16)); ++ return this; ++ } ++ ++ @Override ++ public Builder title(final net.kyori.adventure.text.@Nullable Component title) { ++ this.title = this.conversions.asVanilla(title); ++ return this; ++ } ++ ++ @Override ++ public Builder author(final net.kyori.adventure.text.@Nullable Component author) { ++ this.author = this.conversions.asVanilla(author); ++ return this; ++ } ++ ++ @Override ++ public Builder assetId(final Key assetId) { ++ this.assetId = PaperAdventure.asVanilla(asArgument(assetId, "assetId")); ++ return this; ++ } ++ ++ @Override ++ public PaintingVariant build() { ++ return new PaintingVariant( ++ this.width(), ++ this.height(), ++ asConfigured(this.assetId, "assetId"), ++ Optional.ofNullable(this.title), ++ Optional.ofNullable(this.author) ++ ); ++ } ++ } ++} +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..cfcf814eb527e6b82a2319f28df43b085ca5c168 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/data/package-info.java +@@ -0,0 +1,4 @@ ++@NullMarked ++package io.papermc.paper.registry.data; ++ ++import org.jspecify.annotations.NullMarked; +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..9d61fad3989540b77734e57935104696e3c2b5b8 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/registry/data/util/Checks.java +@@ -0,0 +1,45 @@ ++package io.papermc.paper.registry.data.util; ++ ++import java.util.OptionalInt; ++import org.jspecify.annotations.Nullable; ++ ++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 " + field + " 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 cc3c56224e64816b885c0131ce2a800a2efe3113..7acd9c71c5c4b487e792b8c36a8e52e10b691e98 100644 +--- a/src/main/java/net/minecraft/world/level/gameevent/GameEvent.java ++++ b/src/main/java/net/minecraft/world/level/gameevent/GameEvent.java +@@ -85,7 +85,7 @@ 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 ac9b4328cd55a68664a3f71186bc9a7be7cd9658..ea9fe1f8b1a1685ea975eba0ca418a831006065a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftGameEvent.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftGameEvent.java +@@ -18,10 +18,12 @@ 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; + } + +@@ -30,6 +32,18 @@ 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() { |