Paper/patches/server/0466-Add-RegistryAccess-for-managing-Registries.patch
2024-11-23 20:26:51 +01:00

1419 lines
78 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
Date: Mon, 27 Feb 2023 18:28:39 -0800
Subject: [PATCH] Add RegistryAccess for managing Registries
RegistryAccess is independant from CraftServer and
doesn't require one to be created allowing the
org.bukkit.Registry class to be loaded earlier.
== AT ==
public net.minecraft.server.RegistryLayer STATIC_ACCESS
diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistries.java b/src/main/java/io/papermc/paper/registry/PaperRegistries.java
new file mode 100644
index 0000000000000000000000000000000000000000..2f22f46f80b80be43a2cc1cd8afb51f4d1fd0e91
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/PaperRegistries.java
@@ -0,0 +1,157 @@
+package io.papermc.paper.registry;
+
+import com.google.common.base.Preconditions;
+import io.papermc.paper.adventure.PaperAdventure;
+import io.papermc.paper.registry.entry.RegistryEntry;
+import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import net.minecraft.core.Registry;
+import net.minecraft.core.registries.Registries;
+import net.minecraft.resources.ResourceKey;
+import org.bukkit.Art;
+import org.bukkit.Fluid;
+import org.bukkit.GameEvent;
+import org.bukkit.JukeboxSong;
+import org.bukkit.Keyed;
+import org.bukkit.MusicInstrument;
+import org.bukkit.Sound;
+import org.bukkit.attribute.Attribute;
+import org.bukkit.block.Biome;
+import org.bukkit.block.BlockType;
+import org.bukkit.block.banner.PatternType;
+import org.bukkit.craftbukkit.CraftArt;
+import org.bukkit.craftbukkit.CraftFluid;
+import org.bukkit.craftbukkit.CraftGameEvent;
+import org.bukkit.craftbukkit.CraftJukeboxSong;
+import org.bukkit.craftbukkit.CraftMusicInstrument;
+import org.bukkit.craftbukkit.CraftSound;
+import org.bukkit.craftbukkit.attribute.CraftAttribute;
+import org.bukkit.craftbukkit.block.CraftBiome;
+import org.bukkit.craftbukkit.block.CraftBlockType;
+import org.bukkit.craftbukkit.block.banner.CraftPatternType;
+import org.bukkit.craftbukkit.damage.CraftDamageType;
+import org.bukkit.craftbukkit.enchantments.CraftEnchantment;
+import org.bukkit.craftbukkit.entity.CraftCat;
+import org.bukkit.craftbukkit.entity.CraftFrog;
+import org.bukkit.craftbukkit.entity.CraftVillager;
+import org.bukkit.craftbukkit.entity.CraftWolf;
+import org.bukkit.craftbukkit.generator.structure.CraftStructure;
+import org.bukkit.craftbukkit.generator.structure.CraftStructureType;
+import org.bukkit.craftbukkit.inventory.CraftItemType;
+import org.bukkit.craftbukkit.inventory.CraftMenuType;
+import org.bukkit.craftbukkit.inventory.trim.CraftTrimMaterial;
+import org.bukkit.craftbukkit.inventory.trim.CraftTrimPattern;
+import org.bukkit.craftbukkit.legacy.FieldRename;
+import org.bukkit.craftbukkit.map.CraftMapCursor;
+import org.bukkit.craftbukkit.potion.CraftPotionEffectType;
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
+import org.bukkit.damage.DamageType;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.entity.Cat;
+import org.bukkit.entity.Frog;
+import org.bukkit.entity.Villager;
+import org.bukkit.entity.Wolf;
+import org.bukkit.entity.memory.MemoryKey;
+import org.bukkit.generator.structure.Structure;
+import org.bukkit.generator.structure.StructureType;
+import org.bukkit.inventory.ItemType;
+import org.bukkit.inventory.MenuType;
+import org.bukkit.inventory.meta.trim.TrimMaterial;
+import org.bukkit.inventory.meta.trim.TrimPattern;
+import org.bukkit.map.MapCursor;
+import org.bukkit.potion.PotionEffectType;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.checkerframework.framework.qual.DefaultQualifier;
+
+import static io.papermc.paper.registry.entry.RegistryEntry.apiOnly;
+import static io.papermc.paper.registry.entry.RegistryEntry.entry;
+
+@DefaultQualifier(NonNull.class)
+public final class PaperRegistries {
+
+ static final List<RegistryEntry<?, ?>> REGISTRY_ENTRIES;
+ private static final Map<RegistryKey<?>, RegistryEntry<?, ?>> BY_REGISTRY_KEY;
+ private static final Map<ResourceKey<?>, RegistryEntry<?, ?>> BY_RESOURCE_KEY;
+ static {
+ REGISTRY_ENTRIES = List.of(
+ // built-ins
+ entry(Registries.GAME_EVENT, RegistryKey.GAME_EVENT, GameEvent.class, CraftGameEvent::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),
+ entry(Registries.ITEM, RegistryKey.ITEM, ItemType.class, CraftItemType::new),
+ entry(Registries.CAT_VARIANT, RegistryKey.CAT_VARIANT, Cat.Type.class, CraftCat.CraftType::new),
+ entry(Registries.FROG_VARIANT, RegistryKey.FROG_VARIANT, Frog.Variant.class, CraftFrog.CraftVariant::new),
+ entry(Registries.VILLAGER_PROFESSION, RegistryKey.VILLAGER_PROFESSION, Villager.Profession.class, CraftVillager.CraftProfession::new),
+ entry(Registries.VILLAGER_TYPE, RegistryKey.VILLAGER_TYPE, Villager.Type.class, CraftVillager.CraftType::new),
+ entry(Registries.MAP_DECORATION_TYPE, RegistryKey.MAP_DECORATION_TYPE, MapCursor.Type.class, CraftMapCursor.CraftType::new),
+ entry(Registries.MENU, RegistryKey.MENU, MenuType.class, CraftMenuType::new),
+ entry(Registries.ATTRIBUTE, RegistryKey.ATTRIBUTE, Attribute.class, CraftAttribute::new),
+ entry(Registries.FLUID, RegistryKey.FLUID, Fluid.class, CraftFluid::new),
+ entry(Registries.SOUND_EVENT, RegistryKey.SOUND_EVENT, Sound.class, CraftSound::new),
+
+ // data-drivens
+ entry(Registries.BIOME, RegistryKey.BIOME, Biome.class, CraftBiome::new).delayed(),
+ entry(Registries.STRUCTURE, RegistryKey.STRUCTURE, Structure.class, CraftStructure::new).delayed(),
+ entry(Registries.TRIM_MATERIAL, RegistryKey.TRIM_MATERIAL, TrimMaterial.class, CraftTrimMaterial::new).delayed(),
+ 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(),
+ 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(),
+ entry(Registries.INSTRUMENT, RegistryKey.INSTRUMENT, MusicInstrument.class, CraftMusicInstrument::new).delayed(),
+
+ // api-only
+ apiOnly(Registries.ENTITY_TYPE, RegistryKey.ENTITY_TYPE, PaperSimpleRegistry::entityType),
+ apiOnly(Registries.PARTICLE_TYPE, RegistryKey.PARTICLE_TYPE, PaperSimpleRegistry::particleType),
+ apiOnly(Registries.POTION, RegistryKey.POTION, PaperSimpleRegistry::potion),
+ apiOnly(Registries.MEMORY_MODULE_TYPE, RegistryKey.MEMORY_MODULE_TYPE, () -> (org.bukkit.Registry<MemoryKey<?>>) (org.bukkit.Registry) org.bukkit.Registry.MEMORY_MODULE_TYPE)
+ );
+ final Map<RegistryKey<?>, RegistryEntry<?, ?>> byRegistryKey = new IdentityHashMap<>(REGISTRY_ENTRIES.size());
+ final Map<ResourceKey<?>, RegistryEntry<?, ?>> byResourceKey = new IdentityHashMap<>(REGISTRY_ENTRIES.size());
+ for (final RegistryEntry<?, ?> entry : REGISTRY_ENTRIES) {
+ Preconditions.checkState(byRegistryKey.put(entry.apiKey(), entry) == null, "Duplicate api registry key: %s", entry.apiKey());
+ Preconditions.checkState(byResourceKey.put(entry.mcKey(), entry) == null, "Duplicate mc registry key: %s", entry.mcKey());
+ }
+ BY_REGISTRY_KEY = Collections.unmodifiableMap(byRegistryKey);
+ BY_RESOURCE_KEY = Collections.unmodifiableMap(byResourceKey);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <M, T extends Keyed> @Nullable RegistryEntry<M, T> getEntry(final ResourceKey<? extends Registry<M>> resourceKey) {
+ return (RegistryEntry<M, T>) BY_RESOURCE_KEY.get(resourceKey);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <M, T extends Keyed> @Nullable RegistryEntry<M, T> getEntry(final RegistryKey<? super T> registryKey) {
+ return (RegistryEntry<M, T>) BY_REGISTRY_KEY.get(registryKey);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <M, T> RegistryKey<T> registryFromNms(final ResourceKey<? extends Registry<M>> registryResourceKey) {
+ return (RegistryKey<T>) Objects.requireNonNull(BY_RESOURCE_KEY.get(registryResourceKey), registryResourceKey + " doesn't have an api RegistryKey").apiKey();
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <M, T> ResourceKey<? extends Registry<M>> registryToNms(final RegistryKey<T> registryKey) {
+ return (ResourceKey<? extends Registry<M>>) Objects.requireNonNull(BY_REGISTRY_KEY.get(registryKey), registryKey + " doesn't have an mc registry ResourceKey").mcKey();
+ }
+
+ public static <M, T> TypedKey<T> fromNms(final ResourceKey<M> resourceKey) {
+ return TypedKey.create(registryFromNms(resourceKey.registryKey()), CraftNamespacedKey.fromMinecraft(resourceKey.location()));
+ }
+
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ public static <M, T> ResourceKey<M> toNms(final TypedKey<T> typedKey) {
+ return ResourceKey.create((ResourceKey<? extends Registry<M>>) PaperRegistries.registryToNms(typedKey.registryKey()), PaperAdventure.asVanilla(typedKey.key()));
+ }
+
+ private PaperRegistries() {
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java b/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java
new file mode 100644
index 0000000000000000000000000000000000000000..35b6a7c5bac9640332a833bd3627f2bcb1bbf2f3
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java
@@ -0,0 +1,127 @@
+package io.papermc.paper.registry;
+
+import io.papermc.paper.registry.entry.ApiRegistryEntry;
+import io.papermc.paper.registry.entry.RegistryEntry;
+import io.papermc.paper.registry.legacy.DelayedRegistry;
+import io.papermc.paper.registry.legacy.DelayedRegistryEntry;
+import io.papermc.paper.registry.legacy.LegacyRegistryIdentifiers;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+import net.minecraft.resources.ResourceKey;
+import org.bukkit.Keyed;
+import org.bukkit.Registry;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.checkerframework.framework.qual.DefaultQualifier;
+import org.jetbrains.annotations.VisibleForTesting;
+
+import static java.util.Objects.requireNonNull;
+
+@DefaultQualifier(NonNull.class)
+public class PaperRegistryAccess implements RegistryAccess {
+
+ // We store the API registries in a memoized supplier, so they can be created on-demand.
+ // These suppliers are added to this map right after the instance of nms.Registry is created before it is loaded.
+ // We want to do registration there, so we have access to the nms.Registry instance in order to wrap it in a CraftRegistry instance.
+ // The memoized Supplier is needed because we *can't* instantiate any CraftRegistry class until **all** the BuiltInRegistries have been added
+ // to this map because that would class-load org.bukkit.Registry which would query this map.
+ private final Map<RegistryKey<?>, RegistryHolder<?>> registries = new ConcurrentHashMap<>(); // is "identity" because RegistryKey overrides equals and hashCode
+
+ public static PaperRegistryAccess instance() {
+ return (PaperRegistryAccess) RegistryAccessHolder.INSTANCE.orElseThrow(() -> new IllegalStateException("No RegistryAccess implementation found"));
+ }
+
+ @VisibleForTesting
+ public Set<RegistryKey<?>> getLoadedServerBackedRegistries() {
+ return this.registries.keySet().stream().filter(registryHolder -> !(PaperRegistries.getEntry(registryHolder) instanceof ApiRegistryEntry)).collect(Collectors.toUnmodifiableSet());
+ }
+
+ @SuppressWarnings("unchecked")
+ @Deprecated(forRemoval = true)
+ @Override
+ public <T extends Keyed> @Nullable Registry<T> getRegistry(final Class<T> type) {
+ final @Nullable RegistryKey<T> registryKey = byType(type);
+ // If our mapping from Class -> RegistryKey did not contain the passed type it was either a completely invalid type or a registry
+ // that merely exists as a SimpleRegistry in the org.bukkit.Registry type. We cannot return a registry for these, return null
+ // as per method contract in Bukkit#getRegistry.
+ if (registryKey == null) return null;
+
+ final @Nullable RegistryEntry<?, T> entry = PaperRegistries.getEntry(registryKey);
+ final @Nullable RegistryHolder<T> registry = (RegistryHolder<T>) this.registries.get(registryKey);
+ if (registry != null) {
+ // if the registry exists, return right away. Since this is the "legacy" method, we return DelayedRegistry
+ // for the non-builtin Registry instances stored as fields in Registry.
+ return registry.get();
+ } else if (entry instanceof DelayedRegistryEntry<?, T>) {
+ // if the registry doesn't exist and the entry is marked as "delayed", we create a registry holder that is empty
+ // which will later be filled with the actual registry. This is so the fields on org.bukkit.Registry can be populated with
+ // registries that don't exist at the time org.bukkit.Registry is statically initialized.
+ final RegistryHolder<T> delayedHolder = new RegistryHolder.Delayed<>();
+ this.registries.put(registryKey, delayedHolder);
+ return delayedHolder.get();
+ } else {
+ // if the registry doesn't exist yet or doesn't have a delayed entry, just return null
+ return null;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T extends Keyed> Registry<T> getRegistry(final RegistryKey<T> key) {
+ if (PaperRegistries.getEntry(key) == null) {
+ throw new NoSuchElementException(key + " is not a valid registry key");
+ }
+ final @Nullable RegistryHolder<T> registryHolder = (RegistryHolder<T>) this.registries.get(key);
+ if (registryHolder == null) {
+ throw new IllegalArgumentException(key + " points to a registry that is not available yet");
+ }
+ // since this is the getRegistry method that uses the modern RegistryKey, we unwrap any DelayedRegistry instances
+ // that might be returned here. I don't think reference equality is required when doing getRegistry(RegistryKey.WOLF_VARIANT) == Registry.WOLF_VARIANT
+ return possiblyUnwrap(registryHolder.get());
+ }
+
+ private static <T extends Keyed> Registry<T> possiblyUnwrap(final Registry<T> registry) {
+ if (registry instanceof final DelayedRegistry<T, ?> delayedRegistry) { // if not coming from legacy, unwrap the delayed registry
+ return delayedRegistry.delegate();
+ }
+ return registry;
+ }
+
+ public <M> void registerReloadableRegistry(final ResourceKey<? extends net.minecraft.core.Registry<M>> resourceKey, final net.minecraft.core.Registry<M> registry) {
+ this.registerRegistry(resourceKey, registry, true);
+ }
+
+ public <M> void registerRegistry(final ResourceKey<? extends net.minecraft.core.Registry<M>> resourceKey, final net.minecraft.core.Registry<M> registry) {
+ this.registerRegistry(resourceKey, registry, false);
+ }
+
+ @SuppressWarnings("unchecked") // this method should be called right after any new MappedRegistry instances are created to later be used by the server.
+ private <M, B extends Keyed, R extends Registry<B>> void registerRegistry(final ResourceKey<? extends net.minecraft.core.Registry<M>> resourceKey, final net.minecraft.core.Registry<M> registry, final boolean replace) {
+ final @Nullable RegistryEntry<M, B> entry = PaperRegistries.getEntry(resourceKey);
+ if (entry == null) { // skip registries that don't have API entries
+ return;
+ }
+ final @Nullable RegistryHolder<B> registryHolder = (RegistryHolder<B>) this.registries.get(entry.apiKey());
+ if (registryHolder == null || replace) {
+ // if the holder doesn't exist yet, or is marked as "replaceable", put it in the map.
+ this.registries.put(entry.apiKey(), entry.createRegistryHolder(registry));
+ } else {
+ if (registryHolder instanceof RegistryHolder.Delayed<?, ?> && entry instanceof final DelayedRegistryEntry<M, B> delayedEntry) {
+ // if the registry holder is delayed, and the entry is marked as "delayed", then load the holder with the CraftRegistry instance that wraps the actual nms Registry.
+ ((RegistryHolder.Delayed<B, R>) registryHolder).loadFrom(delayedEntry, registry);
+ } else {
+ throw new IllegalArgumentException(resourceKey + " has already been created");
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Deprecated
+ @VisibleForTesting
+ public static <T extends Keyed> @Nullable RegistryKey<T> byType(final Class<T> type) {
+ return (RegistryKey<T>) LegacyRegistryIdentifiers.CLASS_TO_KEY_MAP.get(type);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/PaperSimpleRegistry.java b/src/main/java/io/papermc/paper/registry/PaperSimpleRegistry.java
new file mode 100644
index 0000000000000000000000000000000000000000..6d134ace042758da722960cbcb48e52508dafd61
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/PaperSimpleRegistry.java
@@ -0,0 +1,38 @@
+package io.papermc.paper.registry;
+
+import java.util.function.Predicate;
+import net.minecraft.core.registries.BuiltInRegistries;
+import org.bukkit.Keyed;
+import org.bukkit.Particle;
+import org.bukkit.Registry;
+import org.bukkit.entity.EntityType;
+import org.bukkit.potion.PotionType;
+import org.jspecify.annotations.NullMarked;
+
+@NullMarked
+public class PaperSimpleRegistry<T extends Enum<T> & Keyed, M> extends Registry.SimpleRegistry<T> {
+
+ static Registry<EntityType> entityType() {
+ return new PaperSimpleRegistry<>(EntityType.class, entity -> entity != EntityType.UNKNOWN, BuiltInRegistries.ENTITY_TYPE);
+ }
+
+ static Registry<Particle> particleType() {
+ return new PaperSimpleRegistry<>(Particle.class, BuiltInRegistries.PARTICLE_TYPE);
+ }
+
+ static Registry<PotionType> potion() {
+ return new PaperSimpleRegistry<>(PotionType.class, BuiltInRegistries.POTION);
+ }
+
+ private final net.minecraft.core.Registry<M> nmsRegistry;
+
+ protected PaperSimpleRegistry(final Class<T> type, final net.minecraft.core.Registry<M> nmsRegistry) {
+ super(type);
+ this.nmsRegistry = nmsRegistry;
+ }
+
+ public PaperSimpleRegistry(final Class<T> type, final Predicate<T> predicate, final net.minecraft.core.Registry<M> nmsRegistry) {
+ super(type, predicate);
+ this.nmsRegistry = nmsRegistry;
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/RegistryHolder.java b/src/main/java/io/papermc/paper/registry/RegistryHolder.java
new file mode 100644
index 0000000000000000000000000000000000000000..a31bdd9f02fe75a87fceb2ebe8c36b3232a561cc
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/RegistryHolder.java
@@ -0,0 +1,47 @@
+package io.papermc.paper.registry;
+
+import com.google.common.base.Suppliers;
+import io.papermc.paper.registry.legacy.DelayedRegistry;
+import io.papermc.paper.registry.legacy.DelayedRegistryEntry;
+import java.util.function.Supplier;
+import org.bukkit.Keyed;
+import org.bukkit.Registry;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
+
+@DefaultQualifier(NonNull.class)
+public interface RegistryHolder<B extends Keyed> {
+
+ Registry<B> get();
+
+ final class Memoized<B extends Keyed, R extends Registry<B>> implements RegistryHolder<B> {
+
+ private final Supplier<R> memoizedSupplier;
+
+ public Memoized(final Supplier<? extends R> supplier) {
+ this.memoizedSupplier = Suppliers.memoize(supplier::get);
+ }
+
+ public Registry<B> get() {
+ return this.memoizedSupplier.get();
+ }
+ }
+
+ final class Delayed<B extends Keyed, R extends Registry<B>> implements RegistryHolder<B> {
+
+ private final DelayedRegistry<B, R> delayedRegistry = new DelayedRegistry<>();
+
+ @Override
+ public DelayedRegistry<B, R> get() {
+ return this.delayedRegistry;
+ }
+
+ <M> void loadFrom(final DelayedRegistryEntry<M, B> delayedEntry, final net.minecraft.core.Registry<M> registry) {
+ final RegistryHolder<B> delegateHolder = delayedEntry.delegate().createRegistryHolder(registry);
+ if (!(delegateHolder instanceof RegistryHolder.Memoized<B, ?>)) {
+ throw new IllegalArgumentException(delegateHolder + " must be a memoized holder");
+ }
+ this.delayedRegistry.load(((Memoized<B, R>) delegateHolder).memoizedSupplier);
+ }
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/entry/ApiRegistryEntry.java b/src/main/java/io/papermc/paper/registry/entry/ApiRegistryEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..2295b0d145cbaabef5d29482c817575dcbe2ba54
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/entry/ApiRegistryEntry.java
@@ -0,0 +1,27 @@
+package io.papermc.paper.registry.entry;
+
+import io.papermc.paper.registry.RegistryHolder;
+import io.papermc.paper.registry.RegistryKey;
+import java.util.function.Supplier;
+import net.minecraft.core.Registry;
+import net.minecraft.resources.ResourceKey;
+import org.bukkit.Keyed;
+
+public class ApiRegistryEntry<M, B extends Keyed> extends BaseRegistryEntry<M, B> {
+
+ private final Supplier<org.bukkit.Registry<B>> registrySupplier;
+
+ protected ApiRegistryEntry(
+ final ResourceKey<? extends Registry<M>> mcKey,
+ final RegistryKey<B> apiKey,
+ final Supplier<org.bukkit.Registry<B>> registrySupplier
+ ) {
+ super(mcKey, apiKey);
+ this.registrySupplier = registrySupplier;
+ }
+
+ @Override
+ public RegistryHolder<B> createRegistryHolder(final Registry<M> nmsRegistry) {
+ return new RegistryHolder.Memoized<>(this.registrySupplier);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/entry/BaseRegistryEntry.java b/src/main/java/io/papermc/paper/registry/entry/BaseRegistryEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..ceb217dbbb84e8bd51365dd47bf91971e364d298
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/entry/BaseRegistryEntry.java
@@ -0,0 +1,27 @@
+package io.papermc.paper.registry.entry;
+
+import io.papermc.paper.registry.RegistryKey;
+import net.minecraft.core.Registry;
+import net.minecraft.resources.ResourceKey;
+import org.bukkit.Keyed;
+
+public abstract class BaseRegistryEntry<M, B extends Keyed> implements RegistryEntry<M, B> { // TODO remove Keyed
+
+ private final ResourceKey<? extends Registry<M>> minecraftRegistryKey;
+ private final RegistryKey<B> apiRegistryKey;
+
+ protected BaseRegistryEntry(final ResourceKey<? extends Registry<M>> minecraftRegistryKey, final RegistryKey<B> apiRegistryKey) {
+ this.minecraftRegistryKey = minecraftRegistryKey;
+ this.apiRegistryKey = apiRegistryKey;
+ }
+
+ @Override
+ public final ResourceKey<? extends Registry<M>> mcKey() {
+ return this.minecraftRegistryKey;
+ }
+
+ @Override
+ public final RegistryKey<B> apiKey() {
+ return this.apiRegistryKey;
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/entry/CraftRegistryEntry.java b/src/main/java/io/papermc/paper/registry/entry/CraftRegistryEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..9bb4aa926978f117901c9f99c45a6862a1d5ce30
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/entry/CraftRegistryEntry.java
@@ -0,0 +1,51 @@
+package io.papermc.paper.registry.entry;
+
+import com.google.common.base.Preconditions;
+import io.papermc.paper.registry.RegistryHolder;
+import io.papermc.paper.registry.RegistryKey;
+import java.util.function.BiFunction;
+import net.minecraft.core.Registry;
+import net.minecraft.resources.ResourceKey;
+import org.bukkit.Keyed;
+import org.bukkit.NamespacedKey;
+import org.bukkit.craftbukkit.CraftRegistry;
+import org.bukkit.craftbukkit.util.ApiVersion;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
+
+@DefaultQualifier(NonNull.class)
+public class CraftRegistryEntry<M, B extends Keyed> extends BaseRegistryEntry<M, B> { // TODO remove Keyed
+
+ private static final BiFunction<NamespacedKey, ApiVersion, NamespacedKey> EMPTY = (namespacedKey, apiVersion) -> namespacedKey;
+
+ protected final Class<?> classToPreload;
+ protected final BiFunction<NamespacedKey, M, B> minecraftToBukkit;
+ protected BiFunction<NamespacedKey, ApiVersion, NamespacedKey> updater = EMPTY;
+
+ protected CraftRegistryEntry(
+ final ResourceKey<? extends Registry<M>> mcKey,
+ final RegistryKey<B> apiKey,
+ final Class<?> classToPreload,
+ final BiFunction<NamespacedKey, M, B> minecraftToBukkit
+ ) {
+ super(mcKey, apiKey);
+ Preconditions.checkArgument(!classToPreload.getPackageName().startsWith("net.minecraft"), classToPreload + " should not be in the net.minecraft package as the class-to-preload");
+ this.classToPreload = classToPreload;
+ this.minecraftToBukkit = minecraftToBukkit;
+ }
+
+ @Override
+ public RegistryEntry<M, B> withSerializationUpdater(final BiFunction<NamespacedKey, ApiVersion, NamespacedKey> updater) {
+ this.updater = updater;
+ return this;
+ }
+
+ @Override
+ public RegistryHolder<B> createRegistryHolder(final Registry<M> nmsRegistry) {
+ return new RegistryHolder.Memoized<>(() -> this.createApiRegistry(nmsRegistry));
+ }
+
+ private CraftRegistry<B, M> createApiRegistry(final Registry<M> nmsRegistry) {
+ return new CraftRegistry<>(this.classToPreload, nmsRegistry, this.minecraftToBukkit, this.updater);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/entry/RegistryEntry.java b/src/main/java/io/papermc/paper/registry/entry/RegistryEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..15991bf13894d850f360a520d1815711d25973ec
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/entry/RegistryEntry.java
@@ -0,0 +1,51 @@
+package io.papermc.paper.registry.entry;
+
+import io.papermc.paper.registry.RegistryHolder;
+import io.papermc.paper.registry.RegistryKey;
+import io.papermc.paper.registry.legacy.DelayedRegistryEntry;
+import java.util.function.BiFunction;
+import java.util.function.Supplier;
+import net.minecraft.core.Registry;
+import net.minecraft.resources.ResourceKey;
+import org.bukkit.Keyed;
+import org.bukkit.NamespacedKey;
+import org.bukkit.craftbukkit.util.ApiVersion;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
+
+@DefaultQualifier(NonNull.class)
+public interface RegistryEntry<M, B extends Keyed> extends RegistryEntryInfo<M, B> { // TODO remove Keyed
+
+ RegistryHolder<B> createRegistryHolder(Registry<M> nmsRegistry);
+
+ default RegistryEntry<M, B> withSerializationUpdater(final BiFunction<NamespacedKey, ApiVersion, NamespacedKey> updater) {
+ return this;
+ }
+
+ /**
+ * This should only be used if the registry instance needs to exist early due to the need
+ * to populate a field in {@link org.bukkit.Registry}. Data-driven registries shouldn't exist
+ * as fields, but instead be obtained via {@link io.papermc.paper.registry.RegistryAccess#getRegistry(RegistryKey)}
+ */
+ @Deprecated
+ default RegistryEntry<M, B> delayed() {
+ return new DelayedRegistryEntry<>(this);
+ }
+
+ static <M, B extends Keyed> RegistryEntry<M, B> entry(
+ final ResourceKey<? extends Registry<M>> mcKey,
+ final RegistryKey<B> apiKey,
+ final Class<?> classToPreload,
+ final BiFunction<NamespacedKey, M, B> minecraftToBukkit
+ ) {
+ return new CraftRegistryEntry<>(mcKey, apiKey, classToPreload, minecraftToBukkit);
+ }
+
+ static <M, B extends Keyed> RegistryEntry<M, B> apiOnly(
+ final ResourceKey<? extends Registry<M>> mcKey,
+ final RegistryKey<B> apiKey,
+ final Supplier<org.bukkit.Registry<B>> apiRegistrySupplier
+ ) {
+ return new ApiRegistryEntry<>(mcKey, apiKey, apiRegistrySupplier);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/entry/RegistryEntryInfo.java b/src/main/java/io/papermc/paper/registry/entry/RegistryEntryInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..0ae855e80fc9fddfc1feb33c7a9748204828b7cc
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/entry/RegistryEntryInfo.java
@@ -0,0 +1,12 @@
+package io.papermc.paper.registry.entry;
+
+import io.papermc.paper.registry.RegistryKey;
+import net.minecraft.core.Registry;
+import net.minecraft.resources.ResourceKey;
+
+public interface RegistryEntryInfo<M, B> {
+
+ ResourceKey<? extends Registry<M>> mcKey();
+
+ RegistryKey<B> apiKey();
+}
diff --git a/src/main/java/io/papermc/paper/registry/entry/package-info.java b/src/main/java/io/papermc/paper/registry/entry/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..e4c94d6860e0f5b643cde1ded20b5503c02a4866
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/entry/package-info.java
@@ -0,0 +1,5 @@
+@DefaultQualifier(NonNull.class)
+package io.papermc.paper.registry.entry;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
diff --git a/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistry.java b/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistry.java
new file mode 100644
index 0000000000000000000000000000000000000000..9400fed345344a0a8e4fb301cca6a1867adf625b
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistry.java
@@ -0,0 +1,61 @@
+package io.papermc.paper.registry.legacy;
+
+import java.util.Iterator;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+import net.kyori.adventure.key.Key;
+import org.bukkit.Keyed;
+import org.bukkit.NamespacedKey;
+import org.bukkit.Registry;
+import org.bukkit.craftbukkit.CraftRegistry;
+import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * This is to support the now-deprecated fields in {@link Registry} for
+ * data-driven registries.
+ */
+public final class DelayedRegistry<T extends Keyed, R extends Registry<T>> implements Registry<T> {
+
+ private @MonotonicNonNull Supplier<? extends R> delegate;
+
+ public void load(final Supplier<? extends R> registry) {
+ if (this.delegate != null) {
+ throw new IllegalStateException("Registry already loaded!");
+ }
+ this.delegate = registry;
+ }
+
+ public Registry<T> delegate() {
+ if (this.delegate == null) {
+ throw new IllegalStateException("You are trying to access this registry too early!");
+ }
+ return this.delegate.get();
+ }
+
+ @Override
+ public @Nullable T get(final NamespacedKey key) {
+ return this.delegate().get(key);
+ }
+
+ @Override
+ public @NotNull T getOrThrow(@NotNull final NamespacedKey key) {
+ return this.delegate().getOrThrow(key);
+ }
+
+ @Override
+ public Iterator<T> iterator() {
+ return this.delegate().iterator();
+ }
+
+ @Override
+ public Stream<T> stream() {
+ return this.delegate().stream();
+ }
+
+ @Override
+ public NamespacedKey getKey(final T value) {
+ return this.delegate().getKey(value);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistryEntry.java b/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistryEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..110b8d559f49f9e4f181b47663962a139a273a72
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistryEntry.java
@@ -0,0 +1,26 @@
+package io.papermc.paper.registry.legacy;
+
+import io.papermc.paper.registry.RegistryHolder;
+import io.papermc.paper.registry.RegistryKey;
+import io.papermc.paper.registry.entry.RegistryEntry;
+import net.minecraft.core.Registry;
+import net.minecraft.resources.ResourceKey;
+import org.bukkit.Keyed;
+
+public record DelayedRegistryEntry<M, T extends Keyed>(RegistryEntry<M, T> delegate) implements RegistryEntry<M, T> {
+
+ @Override
+ public ResourceKey<? extends Registry<M>> mcKey() {
+ return this.delegate.mcKey();
+ }
+
+ @Override
+ public RegistryKey<T> apiKey() {
+ return this.delegate.apiKey();
+ }
+
+ @Override
+ public RegistryHolder<T> createRegistryHolder(final Registry<M> nmsRegistry) {
+ return this.delegate.createRegistryHolder(nmsRegistry);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/legacy/LegacyRegistryIdentifiers.java b/src/main/java/io/papermc/paper/registry/legacy/LegacyRegistryIdentifiers.java
new file mode 100644
index 0000000000000000000000000000000000000000..83870816cd4c54f94a3c603ffe41c11e457f3dec
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/legacy/LegacyRegistryIdentifiers.java
@@ -0,0 +1,33 @@
+package io.papermc.paper.registry.legacy;
+
+import com.google.common.collect.ImmutableMap;
+import io.leangen.geantyref.GenericTypeReflector;
+import io.papermc.paper.registry.RegistryKey;
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.util.Map;
+
+@Deprecated
+public final class LegacyRegistryIdentifiers {
+
+ public static final Map<Class<?>, RegistryKey<?>> CLASS_TO_KEY_MAP;
+
+ static {
+ final ImmutableMap.Builder<Class<?>, RegistryKey<?>> builder = ImmutableMap.builder();
+ try {
+ for (final Field field : RegistryKey.class.getFields()) {
+ if (field.getType() == RegistryKey.class) {
+ // get the legacy type from the RegistryKey generic parameter on the field
+ final Class<?> legacyType = GenericTypeReflector.erase(((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]);
+ builder.put(legacyType, (RegistryKey<?>) field.get(null));
+ }
+ }
+ } catch (final ReflectiveOperationException ex) {
+ throw new RuntimeException(ex);
+ }
+ CLASS_TO_KEY_MAP = builder.build();
+ }
+
+ private LegacyRegistryIdentifiers() {
+ }
+}
diff --git a/src/main/java/io/papermc/paper/registry/legacy/package-info.java b/src/main/java/io/papermc/paper/registry/legacy/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..4396982af55872fafbfeaf8161ad6f392726c773
--- /dev/null
+++ b/src/main/java/io/papermc/paper/registry/legacy/package-info.java
@@ -0,0 +1,5 @@
+@DefaultQualifier(NonNull.class)
+package io.papermc.paper.registry.legacy;
+
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.framework.qual.DefaultQualifier;
diff --git a/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java b/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java
index 3f72e30b57fb2a4231e22a2234729408c1240af4..4638ba98dbbdb0f880337347be85a6e0fbed2191 100644
--- a/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java
+++ b/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java
@@ -323,6 +323,7 @@ public class BuiltInRegistries {
ResourceKey<? extends Registry<T>> key, R registry, BuiltInRegistries.RegistryBootstrap<T> initializer
) {
Bootstrap.checkBootstrapCalled(() -> "registry " + key.location());
+ io.papermc.paper.registry.PaperRegistryAccess.instance().registerRegistry(registry.key(), registry); // Paper - initialize API registry
ResourceLocation resourceLocation = key.location();
LOADERS.put(resourceLocation, () -> initializer.run(registry));
WRITABLE_REGISTRY.register((ResourceKey)key, registry, RegistrationInfo.BUILT_IN); // Paper - decompile fix
diff --git a/src/main/java/net/minecraft/resources/RegistryDataLoader.java b/src/main/java/net/minecraft/resources/RegistryDataLoader.java
index a75f6fefdd72188fa8d16df2b5cbb34c4129f52d..61774165a25209ee6d26cf8d80149b220c3874e6 100644
--- a/src/main/java/net/minecraft/resources/RegistryDataLoader.java
+++ b/src/main/java/net/minecraft/resources/RegistryDataLoader.java
@@ -351,6 +351,7 @@ public class RegistryDataLoader {
RegistryDataLoader.Loader<T> create(Lifecycle lifecycle, Map<ResourceKey<?>, Exception> errors) {
WritableRegistry<T> writableRegistry = new MappedRegistry<>(this.key, lifecycle);
+ io.papermc.paper.registry.PaperRegistryAccess.instance().registerRegistry(this.key, writableRegistry); // Paper - initialize API registry
return new RegistryDataLoader.Loader<>(this, writableRegistry, errors);
}
diff --git a/src/main/java/net/minecraft/server/ReloadableServerRegistries.java b/src/main/java/net/minecraft/server/ReloadableServerRegistries.java
index 8e8d6214adbd21a221147f0fc0d91cd9c06a080c..6fddef967b6314ca0158f5bd4b8898670ea5e9ec 100644
--- a/src/main/java/net/minecraft/server/ReloadableServerRegistries.java
+++ b/src/main/java/net/minecraft/server/ReloadableServerRegistries.java
@@ -64,6 +64,7 @@ public class ReloadableServerRegistries {
) {
return CompletableFuture.supplyAsync(() -> {
WritableRegistry<T> writableRegistry = new MappedRegistry<>(type.registryKey(), Lifecycle.experimental());
+ io.papermc.paper.registry.PaperRegistryAccess.instance().registerReloadableRegistry(type.registryKey(), writableRegistry); // Paper - register reloadable registry
Map<ResourceLocation, T> map = new HashMap<>();
String string = Registries.elementsDirPath(type.registryKey());
SimpleJsonResourceReloadListener.scanDirectory(resourceManager, string, ops, type.codec(), map);
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
index 0d091c7b328fb70a82f5b5ded7dec61b7cd3d59a..249f0dcad04a35244da6dab837a461bb42aad00a 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
@@ -127,96 +127,12 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
+ ", this can happen if a plugin creates its own registry entry with out properly registering it.");
}
- /**
- * Note: Newly added registries should also be added to RegistriesArgumentProvider in the test package
- *
- * @param bukkitClass the bukkit class of the registry
- * @param registryHolder the minecraft registry holder
- * @return the bukkit registry of the provided class
- */
- public static <B extends Keyed> Registry<?> createRegistry(Class<? super B> bukkitClass, RegistryAccess registryHolder) {
- if (bukkitClass == Art.class) {
- return new CraftRegistry<>(Art.class, registryHolder.lookupOrThrow(Registries.PAINTING_VARIANT), CraftArt::new, FieldRename.NONE);
- }
- if (bukkitClass == Attribute.class) {
- return new CraftRegistry<>(Attribute.class, registryHolder.lookupOrThrow(Registries.ATTRIBUTE), CraftAttribute::new, FieldRename.ATTRIBUTE_RENAME);
- }
- if (bukkitClass == Biome.class) {
- return new CraftRegistry<>(Biome.class, registryHolder.lookupOrThrow(Registries.BIOME), CraftBiome::new, FieldRename.BIOME_RENAME);
- }
- if (bukkitClass == Enchantment.class) {
- return new CraftRegistry<>(Enchantment.class, registryHolder.lookupOrThrow(Registries.ENCHANTMENT), CraftEnchantment::new, FieldRename.ENCHANTMENT_RENAME);
- }
- if (bukkitClass == Fluid.class) {
- return new CraftRegistry<>(Fluid.class, registryHolder.lookupOrThrow(Registries.FLUID), CraftFluid::new, FieldRename.NONE);
- }
- if (bukkitClass == GameEvent.class) {
- return new CraftRegistry<>(GameEvent.class, registryHolder.lookupOrThrow(Registries.GAME_EVENT), CraftGameEvent::new, FieldRename.NONE);
- }
- if (bukkitClass == MusicInstrument.class) {
- return new CraftRegistry<>(MusicInstrument.class, registryHolder.lookupOrThrow(Registries.INSTRUMENT), CraftMusicInstrument::new, FieldRename.NONE);
- }
- if (bukkitClass == MenuType.class) {
- return new CraftRegistry<>(MenuType.class, registryHolder.lookupOrThrow(Registries.MENU), CraftMenuType::new, FieldRename.NONE);
- }
- if (bukkitClass == PotionEffectType.class) {
- return new CraftRegistry<>(PotionEffectType.class, registryHolder.lookupOrThrow(Registries.MOB_EFFECT), CraftPotionEffectType::new, FieldRename.NONE);
- }
- if (bukkitClass == Sound.class) {
- return new CraftRegistry<>(Sound.class, registryHolder.lookupOrThrow(Registries.SOUND_EVENT), CraftSound::new, FieldRename.NONE);
- }
- if (bukkitClass == Structure.class) {
- return new CraftRegistry<>(Structure.class, registryHolder.lookupOrThrow(Registries.STRUCTURE), CraftStructure::new, FieldRename.NONE);
- }
- if (bukkitClass == StructureType.class) {
- return new CraftRegistry<>(StructureType.class, registryHolder.lookupOrThrow(Registries.STRUCTURE_TYPE), CraftStructureType::new, FieldRename.NONE);
- }
- if (bukkitClass == Villager.Type.class) {
- return new CraftRegistry<>(Villager.Type.class, registryHolder.lookupOrThrow(Registries.VILLAGER_TYPE), CraftVillager.CraftType::new, FieldRename.NONE);
- }
- if (bukkitClass == Villager.Profession.class) {
- return new CraftRegistry<>(Villager.Profession.class, registryHolder.lookupOrThrow(Registries.VILLAGER_PROFESSION), CraftVillager.CraftProfession::new, FieldRename.NONE);
- }
- if (bukkitClass == TrimMaterial.class) {
- return new CraftRegistry<>(TrimMaterial.class, registryHolder.lookupOrThrow(Registries.TRIM_MATERIAL), CraftTrimMaterial::new, FieldRename.NONE);
- }
- if (bukkitClass == TrimPattern.class) {
- return new CraftRegistry<>(TrimPattern.class, registryHolder.lookupOrThrow(Registries.TRIM_PATTERN), CraftTrimPattern::new, FieldRename.NONE);
- }
- if (bukkitClass == DamageType.class) {
- return new CraftRegistry<>(DamageType.class, registryHolder.lookupOrThrow(Registries.DAMAGE_TYPE), CraftDamageType::new, FieldRename.NONE);
- }
- if (bukkitClass == JukeboxSong.class) {
- return new CraftRegistry<>(JukeboxSong.class, registryHolder.lookupOrThrow(Registries.JUKEBOX_SONG), CraftJukeboxSong::new, FieldRename.NONE);
- }
- if (bukkitClass == Wolf.Variant.class) {
- return new CraftRegistry<>(Wolf.Variant.class, registryHolder.lookupOrThrow(Registries.WOLF_VARIANT), CraftWolf.CraftVariant::new, FieldRename.NONE);
- }
- if (bukkitClass == BlockType.class) {
- return new CraftRegistry<>(BlockType.class, registryHolder.lookupOrThrow(Registries.BLOCK), CraftBlockType::new, FieldRename.NONE);
- }
- if (bukkitClass == ItemType.class) {
- return new CraftRegistry<>(ItemType.class, registryHolder.lookupOrThrow(Registries.ITEM), CraftItemType::new, FieldRename.NONE);
- }
- if (bukkitClass == Frog.Variant.class) {
- return new CraftRegistry<>(Frog.Variant.class, registryHolder.lookupOrThrow(Registries.FROG_VARIANT), CraftFrog.CraftVariant::new, FieldRename.NONE);
- }
- if (bukkitClass == Cat.Type.class) {
- return new CraftRegistry<>(Cat.Type.class, registryHolder.lookupOrThrow(Registries.CAT_VARIANT), CraftCat.CraftType::new, FieldRename.NONE);
- }
- if (bukkitClass == MapCursor.Type.class) {
- return new CraftRegistry<>(MapCursor.Type.class, registryHolder.lookupOrThrow(Registries.MAP_DECORATION_TYPE), CraftMapCursor.CraftType::new, FieldRename.NONE);
- }
- if (bukkitClass == PatternType.class) {
- return new CraftRegistry<>(PatternType.class, registryHolder.lookupOrThrow(Registries.BANNER_PATTERN), CraftPatternType::new, FieldRename.NONE);
- }
-
- return null;
- }
+ // Paper - move to PaperRegistries
+ // Paper - NOTE: As long as all uses of the method below relate to *serialization* via ConfigurationSerializable, it's fine
public static <B extends Keyed> B get(Registry<B> bukkit, NamespacedKey namespacedKey, ApiVersion apiVersion) {
if (bukkit instanceof CraftRegistry<B, ?> craft) {
- return craft.get(namespacedKey, apiVersion);
+ return craft.get(craft.serializationUpdater.apply(namespacedKey, apiVersion)); // Paper
}
if (bukkit instanceof Registry.SimpleRegistry<?> simple) {
@@ -234,23 +150,21 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
return bukkit.get(namespacedKey);
}
- private final Class<? super B> bukkitClass;
+ private final Class<?> bukkitClass; // Paper - relax preload class
private final Map<NamespacedKey, B> cache = new HashMap<>();
private final net.minecraft.core.Registry<M> minecraftRegistry;
private final BiFunction<NamespacedKey, M, B> minecraftToBukkit;
- private final BiFunction<NamespacedKey, ApiVersion, NamespacedKey> updater;
+ private final BiFunction<NamespacedKey, ApiVersion, NamespacedKey> serializationUpdater; // Paper - rename to make it *clear* what it is *only* for
private boolean init;
- public CraftRegistry(Class<? super B> bukkitClass, net.minecraft.core.Registry<M> minecraftRegistry, BiFunction<NamespacedKey, M, B> minecraftToBukkit, BiFunction<NamespacedKey, ApiVersion, NamespacedKey> updater) {
+ public CraftRegistry(Class<?> bukkitClass, net.minecraft.core.Registry<M> minecraftRegistry, BiFunction<NamespacedKey, M, B> minecraftToBukkit, BiFunction<NamespacedKey, ApiVersion, NamespacedKey> serializationUpdater) { // Paper - relax preload class
this.bukkitClass = bukkitClass;
this.minecraftRegistry = minecraftRegistry;
this.minecraftToBukkit = minecraftToBukkit;
- this.updater = updater;
+ this.serializationUpdater = serializationUpdater;
}
- public B get(NamespacedKey namespacedKey, ApiVersion apiVersion) {
- return this.get(this.updater.apply(namespacedKey, apiVersion));
- }
+ // Paper - inline into CraftRegistry#get(Registry, NamespacedKey, ApiVersion) above
@Override
public B get(NamespacedKey namespacedKey) {
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index f75d73402cf633254fe1ef4e919f09db48165190..5ae8f646083fb580ac8d28fcbfe8ed2208b45d09 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -284,7 +284,7 @@ public final class CraftServer implements Server {
protected final DedicatedServer console;
protected final DedicatedPlayerList playerList;
private final Map<String, World> worlds = new LinkedHashMap<String, World>();
- private final Map<Class<?>, Registry<?>> registries = new HashMap<>();
+ // private final Map<Class<?>, Registry<?>> registries = new HashMap<>(); // Paper - replace with RegistryAccess
private YamlConfiguration configuration;
private YamlConfiguration commandsConfiguration;
private final Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
@@ -431,6 +431,7 @@ public final class CraftServer implements Server {
}
private void loadCompatibilities() {
+ if (true) return; // Paper - Big nope
ConfigurationSection compatibilities = this.configuration.getConfigurationSection("settings.compatibility");
if (compatibilities == null) {
this.activeCompatibilities = Collections.emptySet();
@@ -2754,7 +2755,7 @@ public final class CraftServer implements Server {
@Override
public <T extends Keyed> Registry<T> getRegistry(Class<T> aClass) {
- return (Registry<T>) this.registries.computeIfAbsent(aClass, key -> CraftRegistry.createRegistry(aClass, this.console.registryAccess()));
+ return io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(aClass); // Paper - replace with RegistryAccess
}
@Deprecated
diff --git a/src/main/java/org/bukkit/craftbukkit/legacy/FieldRename.java b/src/main/java/org/bukkit/craftbukkit/legacy/FieldRename.java
index 091e11934bddb180f0b2e51efb3921c62275d41d..12fe2f8d0dcb715545e071023490a32125b9c4a4 100644
--- a/src/main/java/org/bukkit/craftbukkit/legacy/FieldRename.java
+++ b/src/main/java/org/bukkit/craftbukkit/legacy/FieldRename.java
@@ -51,11 +51,14 @@ public class FieldRename {
};
}
- @RequireCompatibility("allow-old-keys-in-registry")
- public static <T extends Keyed> T get(Registry<T> registry, NamespacedKey namespacedKey) {
- // We don't have version-specific changes, so just use current, and don't inject a version
- return CraftRegistry.get(registry, namespacedKey, ApiVersion.CURRENT);
- }
+ // Paper start - absolutely not, having this as an expectation for plugin developers opens a huge
+ // can of worms in the future, especially if mojang comes back and reuses some old key
+ //@RequireCompatibility("allow-old-keys-in-registry")
+ //public static <T extends Keyed> T get(Registry<T> registry, NamespacedKey namespacedKey) {
+ // // We don't have version-specific changes, so just use current, and don't inject a version
+ // return CraftRegistry.get(registry, namespacedKey, ApiVersion.CURRENT);
+ //}
+ // Paper end
// PatternType
private static final FieldRenameData PATTERN_TYPE_DATA = FieldRenameData.Builder.newBuilder()
diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
index 61d617d4abb9c9cf5c711459aa98c8b173597a9a..c9b789c2a904c2caff516ee9aeff4a6b368766f4 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
@@ -220,20 +220,10 @@ public class Commodore {
public byte[] convert(byte[] b, final String pluginName, final ApiVersion pluginVersion, final Set<String> activeCompatibilities) {
final boolean modern = pluginVersion.isNewerThanOrSameAs(ApiVersion.FLATTENING);
- final boolean enumCompatibility = pluginVersion.isOlderThanOrSameAs(ApiVersion.getOrCreateVersion("1.20.6")) && activeCompatibilities.contains("enum-compatibility-mode");
ClassReader cr = new ClassReader(b);
ClassWriter cw = new ClassWriter(cr, 0);
- List<String> methodEnumSignatures = Commodore.getMethodSignatures(b);
- Multimap<String, String> enumLessToEnum = HashMultimap.create();
- for (String method : methodEnumSignatures) {
- enumLessToEnum.put(method.replace("Ljava/lang/Enum;", "Ljava/lang/Object;"), method);
- }
-
ClassVisitor visitor = cw;
- if (enumCompatibility) {
- visitor = new LimitedClassRemapper(cw, new SimpleRemapper(Commodore.ENUM_RENAMES));
- }
visitor = io.papermc.paper.pluginremap.reflect.ReflectionRemapper.visitor(visitor); // Paper
cr.accept(new ClassRemapper(new ClassVisitor(Opcodes.ASM9, visitor) {
@@ -300,15 +290,6 @@ public class Commodore {
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
- if (enumCompatibility && (access & Opcodes.ACC_SYNTHETIC) != 0 && (access & Opcodes.ACC_BRIDGE) != 0 && desc.contains("Ljava/lang/Object;")) {
- // SPIGOT-7820: Do not use object method if enum method is present
- // The object method does only redirect to the enum method
- Collection<String> result = enumLessToEnum.get(desc.replace("Ljava/lang/Enum;", "Ljava/lang/Object;") + " " + name);
- if (result.size() == 2) {
- name = name + "_BUKKIT_UNUSED";
- }
- }
-
return new MethodVisitor(this.api, super.visitMethod(access, name, desc, signature, exceptions)) {
// Paper start - Plugin rewrites
@Override
diff --git a/src/main/resources/META-INF/services/io.papermc.paper.registry.RegistryAccess b/src/main/resources/META-INF/services/io.papermc.paper.registry.RegistryAccess
new file mode 100644
index 0000000000000000000000000000000000000000..8a083d45004f82fc9c51c219fb20f34624adb501
--- /dev/null
+++ b/src/main/resources/META-INF/services/io.papermc.paper.registry.RegistryAccess
@@ -0,0 +1 @@
+io.papermc.paper.registry.PaperRegistryAccess
diff --git a/src/main/resources/configurations/bukkit.yml b/src/main/resources/configurations/bukkit.yml
index 543e37737bc6fdca23ed9ed0606805d345515a5a..eef7c125b2689f29cae5464659eacdf33f5695b2 100644
--- a/src/main/resources/configurations/bukkit.yml
+++ b/src/main/resources/configurations/bukkit.yml
@@ -23,9 +23,6 @@ settings:
shutdown-message: Server closed
minimum-api: none
use-map-color-cache: true
- compatibility:
- allow-old-keys-in-registry: false
- enum-compatibility-mode: false
spawn-limits:
monsters: 70
animals: 10
diff --git a/src/test/java/io/papermc/paper/registry/LegacyRegistryIdentifierTest.java b/src/test/java/io/papermc/paper/registry/LegacyRegistryIdentifierTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a80b0ded74c0be657e734de61cbf5e32e16c26a8
--- /dev/null
+++ b/src/test/java/io/papermc/paper/registry/LegacyRegistryIdentifierTest.java
@@ -0,0 +1,21 @@
+package io.papermc.paper.registry;
+
+import org.bukkit.GameEvent;
+import org.bukkit.MusicInstrument;
+import org.bukkit.inventory.meta.trim.TrimPattern;
+import org.bukkit.support.environment.VanillaFeature;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertSame;
+
+@Deprecated
+@VanillaFeature
+class LegacyRegistryIdentifierTest {
+
+ @Test
+ void testSeveralConversions() {
+ assertSame(RegistryKey.GAME_EVENT, PaperRegistryAccess.byType(GameEvent.class));
+ assertSame(RegistryKey.TRIM_PATTERN, PaperRegistryAccess.byType(TrimPattern.class));
+ assertSame(RegistryKey.INSTRUMENT, PaperRegistryAccess.byType(MusicInstrument.class));
+ }
+}
diff --git a/src/test/java/io/papermc/paper/registry/RegistryKeyTest.java b/src/test/java/io/papermc/paper/registry/RegistryKeyTest.java
index d8857a05858585113bc7efde3416748effb53d01..41c38b1b6d25c7a7ed08d70b19f5f4a70fc2df94 100644
--- a/src/test/java/io/papermc/paper/registry/RegistryKeyTest.java
+++ b/src/test/java/io/papermc/paper/registry/RegistryKeyTest.java
@@ -1,15 +1,19 @@
package io.papermc.paper.registry;
+import io.papermc.paper.registry.entry.RegistryEntry;
import java.util.Optional;
import java.util.stream.Stream;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
-import org.bukkit.support.AbstractTestingBase;
+import org.bukkit.support.RegistryHelper;
+import org.bukkit.support.environment.AllFeatures;
+import org.checkerframework.checker.nullness.qual.Nullable;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@AllFeatures
@@ -29,6 +33,12 @@ class RegistryKeyTest {
void testApiRegistryKeysExist(final RegistryKey<?> key) {
final Optional<Registry<Object>> registry = RegistryHelper.getRegistry().lookup(ResourceKey.createRegistryKey(ResourceLocation.parse(key.key().asString())));
assertTrue(registry.isPresent(), "Missing vanilla registry for " + key.key().asString());
+ }
+ @ParameterizedTest
+ @MethodSource("data")
+ void testRegistryEntryExists(final RegistryKey<?> key) {
+ final @Nullable RegistryEntry<?, ?> entry = PaperRegistries.getEntry(key);
+ assertNotNull(entry, "Missing PaperRegistries entry for " + key);
}
}
diff --git a/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java b/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java
index b65a3ee68c177da7ef5a57608187dc1672257c7f..c1016e0eb00e952551370c874e8d678fef8ba3dc 100644
--- a/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java
+++ b/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java
@@ -22,14 +22,17 @@ public class RegistryArgumentAddedTest {
// Make sure every registry is created
Class.forName(Registry.class.getName());
- Set<Class<?>> loadedRegistries = new HashSet<>(AllFeaturesExtension.getRealRegistries().keySet());
- Set<Class<?>> notFound = new HashSet<>();
+ // Paper start
+ Set<io.papermc.paper.registry.RegistryKey<?>> loadedRegistries = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>());
+ loadedRegistries.addAll(io.papermc.paper.registry.PaperRegistryAccess.instance().getLoadedServerBackedRegistries());
+ // Paper end
+ Set<io.papermc.paper.registry.RegistryKey<?>> notFound = new HashSet<>(); // Paper
RegistriesArgumentProvider
.getData()
.map(Arguments::get)
.map(array -> array[0])
- .map(clazz -> (Class<?>) clazz)
+ .map(clazz -> (io.papermc.paper.registry.RegistryKey<?>) clazz) // Paper
.forEach(clazz -> {
if (!loadedRegistries.remove(clazz)) {
notFound.add(clazz);
diff --git a/src/test/java/org/bukkit/registry/RegistryConversionTest.java b/src/test/java/org/bukkit/registry/RegistryConversionTest.java
index e97328b95973db52d44bc4d0aefd8eb69f2ebdea..01e351f4e292efe78fc1a1db0f31b2c0a313b101 100644
--- a/src/test/java/org/bukkit/registry/RegistryConversionTest.java
+++ b/src/test/java/org/bukkit/registry/RegistryConversionTest.java
@@ -41,9 +41,9 @@ public class RegistryConversionTest {
@Order(1)
@RegistriesTest
- public void testHandleableImplementation(Class<? extends Keyed> clazz) {
+ public void testHandleableImplementation(io.papermc.paper.registry.RegistryKey<? extends Keyed> type, Class<? extends Keyed> clazz) { // Paper
Set<Class<? extends Keyed>> notImplemented = new HashSet<>();
- Registry<? extends Keyed> registry = Bukkit.getRegistry(clazz);
+ Registry<? extends Keyed> registry = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(type); // Paper
for (Keyed item : registry) {
if (!(item instanceof Handleable<?>)) {
@@ -63,7 +63,7 @@ public class RegistryConversionTest {
@Order(2)
@RegistriesTest
- public void testMinecraftToBukkitPresent(Class<? extends Keyed> clazz, ResourceKey<net.minecraft.core.Registry<?>> registryKey,
+ public void testMinecraftToBukkitPresent(io.papermc.paper.registry.RegistryKey<? extends Keyed> type, Class<? extends Keyed> clazz, ResourceKey<net.minecraft.core.Registry<?>> registryKey,
Class<? extends Keyed> craftClazz, Class<?> minecraftClazz, boolean newMethod) {
String methodName = (newMethod) ? RegistryConversionTest.MINECRAFT_TO_BUKKIT_NEW : RegistryConversionTest.MINECRAFT_TO_BUKKIT;
Method method = null;
@@ -112,7 +112,7 @@ public class RegistryConversionTest {
@Order(2)
@RegistriesTest
- public void testBukkitToMinecraftPresent(Class<? extends Keyed> clazz, ResourceKey<net.minecraft.core.Registry<?>> registryKey,
+ public void testBukkitToMinecraftPresent(io.papermc.paper.registry.RegistryKey<? extends Keyed> type, Class<? extends Keyed> clazz, ResourceKey<net.minecraft.core.Registry<?>> registryKey,
Class<? extends Keyed> craftClazz, Class<?> minecraftClazz, boolean newMethod) {
String methodName = (newMethod) ? RegistryConversionTest.BUKKIT_TO_MINECRAFT_NEW : RegistryConversionTest.BUKKIT_TO_MINECRAFT;
Method method = null;
@@ -159,9 +159,9 @@ public class RegistryConversionTest {
""", minecraftClazz.getName(), methodName, clazz.getSimpleName());
}
- @Order(2)
+ @Order(3)
@RegistriesTest
- public void testMinecraftToBukkitNullValue(Class<? extends Keyed> clazz) throws IllegalAccessException {
+ public void testMinecraftToBukkitNullValue(io.papermc.paper.registry.RegistryKey<? extends Keyed> type, Class<? extends Keyed> clazz) throws IllegalAccessException { // Paper
this.checkValidMinecraftToBukkit(clazz);
try {
@@ -180,7 +180,7 @@ public class RegistryConversionTest {
@Order(3)
@RegistriesTest
- public void testBukkitToMinecraftNullValue(Class<? extends Keyed> clazz) throws IllegalAccessException {
+ public void testBukkitToMinecraftNullValue(io.papermc.paper.registry.RegistryKey<? extends Keyed> type, Class<? extends Keyed> clazz) throws IllegalAccessException { // Paper
this.checkValidBukkitToMinecraft(clazz);
try {
@@ -199,14 +199,14 @@ public class RegistryConversionTest {
@Order(3)
@RegistriesTest
- public void testMinecraftToBukkit(Class<? extends Keyed> clazz) {
+ public void testMinecraftToBukkit(io.papermc.paper.registry.RegistryKey<? extends Keyed> type, Class<? extends Keyed> clazz) { // Paper
this.checkValidMinecraftToBukkit(clazz);
this.checkValidHandle(clazz);
Map<Object, Object> notMatching = new HashMap<>();
Method method = RegistryConversionTest.MINECRAFT_TO_BUKKIT_METHODS.get(clazz);
- RegistryArgumentProvider.getValues(clazz).map(Arguments::get).forEach(arguments -> {
+ RegistryArgumentProvider.getValues(type).map(Arguments::get).forEach(arguments -> { // Paper
Keyed bukkit = (Keyed) arguments[0];
Object minecraft = arguments[1];
@@ -230,14 +230,14 @@ public class RegistryConversionTest {
@Order(3)
@RegistriesTest
- public void testBukkitToMinecraft(Class<? extends Keyed> clazz) {
+ public void testBukkitToMinecraft(io.papermc.paper.registry.RegistryKey<? extends Keyed> type, Class<? extends Keyed> clazz) { // Paper
this.checkValidBukkitToMinecraft(clazz);
this.checkValidHandle(clazz);
Map<Object, Object> notMatching = new HashMap<>();
Method method = RegistryConversionTest.BUKKIT_TO_MINECRAFT_METHODS.get(clazz);
- RegistryArgumentProvider.getValues(clazz).map(Arguments::get).forEach(arguments -> {
+ RegistryArgumentProvider.getValues(type).map(Arguments::get).forEach(arguments -> { // Paper
Keyed bukkit = (Keyed) arguments[0];
Object minecraft = arguments[1];
@@ -265,7 +265,7 @@ public class RegistryConversionTest {
*/
@Order(3)
@RegistriesTest
- public void testMinecraftToBukkitNoValidMinecraft(Class<? extends Keyed> clazz, ResourceKey<net.minecraft.core.Registry<?>> registryKey,
+ public void testMinecraftToBukkitNoValidMinecraft(io.papermc.paper.registry.RegistryKey<? extends Keyed> type, Class<? extends Keyed> clazz, ResourceKey<net.minecraft.core.Registry<?>> registryKey, // Paper
Class<? extends Keyed> craftClazz, Class<?> minecraftClazz) throws IllegalAccessException {
this.checkValidMinecraftToBukkit(clazz);
diff --git a/src/test/java/org/bukkit/support/extension/AllFeaturesExtension.java b/src/test/java/org/bukkit/support/extension/AllFeaturesExtension.java
index e9eb521419bbacb03d7000ace355f2a9f5a6a9c5..8fef8421e3cf87913746a314a477634bd3e99300 100644
--- a/src/test/java/org/bukkit/support/extension/AllFeaturesExtension.java
+++ b/src/test/java/org/bukkit/support/extension/AllFeaturesExtension.java
@@ -39,22 +39,7 @@ public class AllFeaturesExtension extends BaseExtension {
Bukkit.setServer(server);
- when(server.getRegistry(any()))
- .then(invocation -> {
- Class<? extends Keyed> keyed = invocation.getArgument(0);
- if (spyRegistries.containsKey(keyed)) {
- return spyRegistries.get(keyed);
- }
-
- Registry<?> registry = CraftRegistry.createRegistry(keyed, RegistryHelper.getRegistry());
- realRegistries.put(keyed, registry);
-
- Registry<?> spy = mock(registry.getClass(), withSettings().stubOnly().spiedInstance(registry).defaultAnswer(CALLS_REAL_METHODS));
-
- spyRegistries.put(keyed, spy);
-
- return spy;
- });
+ // Paper - Add RegistryAccess for managing registries - replaced with registry access
CraftRegistry.setMinecraftRegistry(RegistryHelper.getRegistry());
}
diff --git a/src/test/java/org/bukkit/support/extension/LegacyExtension.java b/src/test/java/org/bukkit/support/extension/LegacyExtension.java
index 94cf52cf7603e6814682c92b26fcf03a8b927838..c9c3227c3b7fa36ed80f2dc828885a0128e1e3d0 100644
--- a/src/test/java/org/bukkit/support/extension/LegacyExtension.java
+++ b/src/test/java/org/bukkit/support/extension/LegacyExtension.java
@@ -30,11 +30,7 @@ public class LegacyExtension extends BaseExtension {
Bukkit.setServer(server);
- when(server.getRegistry(any()))
- .then(invocation -> {
- Class<? extends Keyed> keyed = invocation.getArgument(0);
- return registries.computeIfAbsent(keyed, k -> CraftRegistry.createRegistry(keyed, RegistryHelper.getRegistry()));
- });
+ // Paper - Add RegistryAccess for managing registries - replaced with registry access
CraftRegistry.setMinecraftRegistry(RegistryHelper.getRegistry());
}
diff --git a/src/test/java/org/bukkit/support/extension/SlowExtension.java b/src/test/java/org/bukkit/support/extension/SlowExtension.java
index e0ce6836d4365c36303f6c675a75ef6a9b047b92..87364f223fbd6185b041138550fcb6e3ed07d1ae 100644
--- a/src/test/java/org/bukkit/support/extension/SlowExtension.java
+++ b/src/test/java/org/bukkit/support/extension/SlowExtension.java
@@ -30,11 +30,7 @@ public class SlowExtension extends BaseExtension {
Bukkit.setServer(server);
- when(server.getRegistry(any()))
- .then(invocation -> {
- Class<? extends Keyed> keyed = invocation.getArgument(0);
- return registries.computeIfAbsent(keyed, k -> CraftRegistry.createRegistry(keyed, RegistryHelper.getRegistry()));
- });
+ // Paper - Add RegistryAccess for managing registries - replaced with registry access
CraftRegistry.setMinecraftRegistry(RegistryHelper.getRegistry());
}
diff --git a/src/test/java/org/bukkit/support/extension/VanillaFeatureExtension.java b/src/test/java/org/bukkit/support/extension/VanillaFeatureExtension.java
index bbd5dd5b27937ddc3d8c57f2b604331495b0f311..626c3033e36897846fe84a77d05e2e91a15598e5 100644
--- a/src/test/java/org/bukkit/support/extension/VanillaFeatureExtension.java
+++ b/src/test/java/org/bukkit/support/extension/VanillaFeatureExtension.java
@@ -30,11 +30,7 @@ public class VanillaFeatureExtension extends BaseExtension {
Bukkit.setServer(server);
- when(server.getRegistry(any()))
- .then(invocation -> {
- Class<? extends Keyed> keyed = invocation.getArgument(0);
- return registries.computeIfAbsent(keyed, k -> CraftRegistry.createRegistry(keyed, RegistryHelper.getRegistry()));
- });
+ // Paper - Add RegistryAccess for managing registries - replaced with registry access
CraftRegistry.setMinecraftRegistry(RegistryHelper.getRegistry());
}
diff --git a/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java b/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java
index bfec6280e8b753a29ad2d9eb88808beb79ec65ea..b717a5ffa567781b0687bbe238b62844214db284 100644
--- a/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java
+++ b/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java
@@ -1,6 +1,7 @@
package org.bukkit.support.provider;
import com.google.common.collect.Lists;
+import io.papermc.paper.registry.RegistryKey;
import java.util.List;
import java.util.stream.Stream;
import net.minecraft.core.registries.Registries;
@@ -73,41 +74,40 @@ public class RegistriesArgumentProvider implements ArgumentsProvider {
private static final List<Arguments> DATA = Lists.newArrayList();
static {
- // Order: Bukkit class, Minecraft Registry key, CraftBukkit class, Minecraft class
- register(Art.class, Registries.PAINTING_VARIANT, CraftArt.class, PaintingVariant.class);
- register(Attribute.class, Registries.ATTRIBUTE, CraftAttribute.class, net.minecraft.world.entity.ai.attributes.Attribute.class);
- register(Biome.class, Registries.BIOME, CraftBiome.class, net.minecraft.world.level.biome.Biome.class);
- register(Enchantment.class, Registries.ENCHANTMENT, CraftEnchantment.class, net.minecraft.world.item.enchantment.Enchantment.class);
- register(Fluid.class, Registries.FLUID, CraftFluid.class, net.minecraft.world.level.material.Fluid.class);
- register(GameEvent.class, Registries.GAME_EVENT, CraftGameEvent.class, net.minecraft.world.level.gameevent.GameEvent.class);
- register(MusicInstrument.class, Registries.INSTRUMENT, CraftMusicInstrument.class, Instrument.class);
- register(MenuType.class, Registries.MENU, CraftMenuType.class, net.minecraft.world.inventory.MenuType.class);
- register(PotionEffectType.class, Registries.MOB_EFFECT, CraftPotionEffectType.class, MobEffect.class);
- register(Sound.class, Registries.SOUND_EVENT, CraftSound.class, SoundEvent.class);
- register(Structure.class, Registries.STRUCTURE, CraftStructure.class, net.minecraft.world.level.levelgen.structure.Structure.class);
- register(StructureType.class, Registries.STRUCTURE_TYPE, CraftStructureType.class, net.minecraft.world.level.levelgen.structure.StructureType.class);
- register(Villager.Type.class, Registries.VILLAGER_TYPE, CraftVillager.CraftType.class, VillagerType.class);
- register(Villager.Profession.class, Registries.VILLAGER_PROFESSION, CraftVillager.CraftProfession.class, VillagerProfession.class);
- register(TrimMaterial.class, Registries.TRIM_MATERIAL, CraftTrimMaterial.class, net.minecraft.world.item.equipment.trim.TrimMaterial.class);
- register(TrimPattern.class, Registries.TRIM_PATTERN, CraftTrimPattern.class, net.minecraft.world.item.equipment.trim.TrimPattern.class);
- register(DamageType.class, Registries.DAMAGE_TYPE, CraftDamageType.class, net.minecraft.world.damagesource.DamageType.class);
- register(JukeboxSong.class, Registries.JUKEBOX_SONG, CraftJukeboxSong.class, net.minecraft.world.item.JukeboxSong.class);
- register(Wolf.Variant.class, Registries.WOLF_VARIANT, CraftWolf.CraftVariant.class, WolfVariant.class);
- register(ItemType.class, Registries.ITEM, CraftItemType.class, net.minecraft.world.item.Item.class, true);
- register(BlockType.class, Registries.BLOCK, CraftBlockType.class, net.minecraft.world.level.block.Block.class, true);
- register(Frog.Variant.class, Registries.FROG_VARIANT, CraftFrog.CraftVariant.class, FrogVariant.class);
- register(Cat.Type.class, Registries.CAT_VARIANT, CraftCat.CraftType.class, CatVariant.class);
- register(MapCursor.Type.class, Registries.MAP_DECORATION_TYPE, CraftMapCursor.CraftType.class, MapDecorationType.class);
- register(PatternType.class, Registries.BANNER_PATTERN, CraftPatternType.class, BannerPattern.class);
-
+ // Order: RegistryKey, Bukkit class, Minecraft Registry key, CraftBukkit class, Minecraft class
+ register(RegistryKey.PAINTING_VARIANT, Art.class, Registries.PAINTING_VARIANT, CraftArt.class, PaintingVariant.class);
+ register(RegistryKey.ATTRIBUTE, Attribute.class, Registries.ATTRIBUTE, CraftAttribute.class, net.minecraft.world.entity.ai.attributes.Attribute.class);
+ register(RegistryKey.BIOME, Biome.class, Registries.BIOME, CraftBiome.class, net.minecraft.world.level.biome.Biome.class);
+ register(RegistryKey.ENCHANTMENT, Enchantment.class, Registries.ENCHANTMENT, CraftEnchantment.class, net.minecraft.world.item.enchantment.Enchantment.class);
+ register(RegistryKey.FLUID, Fluid.class, Registries.FLUID, CraftFluid.class, net.minecraft.world.level.material.Fluid.class);
+ register(RegistryKey.GAME_EVENT, GameEvent.class, Registries.GAME_EVENT, CraftGameEvent.class, net.minecraft.world.level.gameevent.GameEvent.class);
+ register(RegistryKey.INSTRUMENT, MusicInstrument.class, Registries.INSTRUMENT, CraftMusicInstrument.class, Instrument.class);
+ register(RegistryKey.MOB_EFFECT, PotionEffectType.class, Registries.MOB_EFFECT, CraftPotionEffectType.class, MobEffect.class);
+ register(RegistryKey.SOUND_EVENT, Sound.class, Registries.SOUND_EVENT, CraftSound.class, SoundEvent.class);
+ register(RegistryKey.STRUCTURE, Structure.class, Registries.STRUCTURE, CraftStructure.class, net.minecraft.world.level.levelgen.structure.Structure.class);
+ register(RegistryKey.STRUCTURE_TYPE, StructureType.class, Registries.STRUCTURE_TYPE, CraftStructureType.class, net.minecraft.world.level.levelgen.structure.StructureType.class);
+ register(RegistryKey.VILLAGER_TYPE, Villager.Type.class, Registries.VILLAGER_TYPE, CraftVillager.CraftType.class, VillagerType.class);
+ register(RegistryKey.VILLAGER_PROFESSION, Villager.Profession.class, Registries.VILLAGER_PROFESSION, CraftVillager.CraftProfession.class, VillagerProfession.class);
+ register(RegistryKey.TRIM_MATERIAL, TrimMaterial.class, Registries.TRIM_MATERIAL, CraftTrimMaterial.class, net.minecraft.world.item.equipment.trim.TrimMaterial.class);
+ register(RegistryKey.TRIM_PATTERN, TrimPattern.class, Registries.TRIM_PATTERN, CraftTrimPattern.class, net.minecraft.world.item.equipment.trim.TrimPattern.class);
+ register(RegistryKey.DAMAGE_TYPE, DamageType.class, Registries.DAMAGE_TYPE, CraftDamageType.class, net.minecraft.world.damagesource.DamageType.class);
+ register(RegistryKey.JUKEBOX_SONG, JukeboxSong.class, Registries.JUKEBOX_SONG, CraftJukeboxSong.class, net.minecraft.world.item.JukeboxSong.class);
+ register(RegistryKey.WOLF_VARIANT, Wolf.Variant.class, Registries.WOLF_VARIANT, CraftWolf.CraftVariant.class, WolfVariant.class);
+ register(RegistryKey.ITEM, ItemType.class, Registries.ITEM, CraftItemType.class, net.minecraft.world.item.Item.class, true);
+ register(RegistryKey.BLOCK, BlockType.class, Registries.BLOCK, CraftBlockType.class, net.minecraft.world.level.block.Block.class, true);
+ register(RegistryKey.FROG_VARIANT, Frog.Variant.class, Registries.FROG_VARIANT, CraftFrog.CraftVariant.class, FrogVariant.class);
+ register(RegistryKey.CAT_VARIANT, Cat.Type.class, Registries.CAT_VARIANT, CraftCat.CraftType.class, CatVariant.class);
+ register(RegistryKey.MAP_DECORATION_TYPE, MapCursor.Type.class, Registries.MAP_DECORATION_TYPE, CraftMapCursor.CraftType.class, MapDecorationType.class);
+ register(RegistryKey.BANNER_PATTERN, PatternType.class, Registries.BANNER_PATTERN, CraftPatternType.class, BannerPattern.class);
+ register(RegistryKey.MENU, MenuType.class, Registries.MENU, CraftMenuType.class, net.minecraft.world.inventory.MenuType.class);
}
- private static void register(Class bukkit, ResourceKey registry, Class craft, Class minecraft) {
- RegistriesArgumentProvider.register(bukkit, registry, craft, minecraft, false);
+ private static void register(RegistryKey registryKey, Class bukkit, ResourceKey registry, Class craft, Class minecraft) { // Paper
+ RegistriesArgumentProvider.register(registryKey, bukkit, registry, craft, minecraft, false);
}
- private static void register(Class bukkit, ResourceKey registry, Class craft, Class minecraft, boolean newClass) {
- RegistriesArgumentProvider.DATA.add(Arguments.of(bukkit, registry, craft, minecraft, newClass));
+ private static void register(RegistryKey registryKey, Class bukkit, ResourceKey registry, Class craft, Class minecraft, boolean newClass) { // Paper
+ RegistriesArgumentProvider.DATA.add(Arguments.of(registryKey, bukkit, registry, craft, minecraft, newClass));
}
@Override
diff --git a/src/test/java/org/bukkit/support/provider/RegistryArgumentProvider.java b/src/test/java/org/bukkit/support/provider/RegistryArgumentProvider.java
index f2ceb5e67536dfa5de792dc64a7898fd2e8aa810..beb5fc9e721f5de54064c3d241df9ca9f4cd4f65 100644
--- a/src/test/java/org/bukkit/support/provider/RegistryArgumentProvider.java
+++ b/src/test/java/org/bukkit/support/provider/RegistryArgumentProvider.java
@@ -22,11 +22,11 @@ public class RegistryArgumentProvider implements ArgumentsProvider, AnnotationCo
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) throws Exception {
- return RegistryArgumentProvider.getValues(this.registryType);
+ return RegistryArgumentProvider.getValues(io.papermc.paper.registry.PaperRegistryAccess.byType(this.registryType)); // Paper
}
- public static Stream<? extends Arguments> getValues(Class<? extends Keyed> registryType) {
- Registry<?> registry = Bukkit.getRegistry(registryType);
+ public static Stream<? extends Arguments> getValues(io.papermc.paper.registry.RegistryKey<? extends Keyed> registryType) { // Paper
+ Registry<?> registry = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(registryType); // Paper
return registry.stream().map(keyed -> (Handleable<?>) keyed)
.map(handleAble -> Arguments.of(handleAble, handleAble.getHandle()));
}