From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Jake Potrebic 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..0000000000000000000000000000000000000000 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/PaperRegistries.java @@ -0,0 +0,0 @@ +package io.papermc.paper.registry; + +import io.papermc.paper.registry.entry.RegistryEntry; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.level.levelgen.structure.Structure; +import org.bukkit.GameEvent; +import org.bukkit.Keyed; +import org.bukkit.MusicInstrument; +import org.bukkit.craftbukkit.CraftGameEvent; +import org.bukkit.craftbukkit.CraftMusicInstrument; +import org.bukkit.craftbukkit.damage.CraftDamageType; +import org.bukkit.craftbukkit.enchantments.CraftEnchantment; +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.trim.CraftTrimMaterial; +import org.bukkit.craftbukkit.inventory.trim.CraftTrimPattern; +import org.bukkit.craftbukkit.potion.CraftPotionEffectType; +import org.bukkit.damage.DamageType; +import org.bukkit.entity.Wolf; +import org.bukkit.entity.memory.MemoryKey; +import org.bukkit.generator.structure.StructureType; +import org.bukkit.inventory.meta.trim.TrimMaterial; +import org.bukkit.inventory.meta.trim.TrimPattern; +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> REGISTRY_ENTRIES; + private static final Map, RegistryEntry> BY_REGISTRY_KEY; + private static final Map, RegistryEntry> BY_RESOURCE_KEY; + static { + REGISTRY_ENTRIES = List.of( + // built-ins + entry(Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT, Enchantment.class, CraftEnchantment::new), + entry(Registries.GAME_EVENT, RegistryKey.GAME_EVENT, GameEvent.class, CraftGameEvent::new), + entry(Registries.INSTRUMENT, RegistryKey.INSTRUMENT, MusicInstrument.class, CraftMusicInstrument::new), + entry(Registries.MOB_EFFECT, RegistryKey.MOB_EFFECT, PotionEffectType.class, CraftPotionEffectType::new), + entry(Registries.STRUCTURE_TYPE, RegistryKey.STRUCTURE_TYPE, StructureType.class, CraftStructureType::new), + + // data-drivens + 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(), + + // api-only + apiOnly(Registries.BIOME, RegistryKey.BIOME, () -> org.bukkit.Registry.BIOME), + apiOnly(Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT, () -> org.bukkit.Registry.ART), + apiOnly(Registries.ATTRIBUTE, RegistryKey.ATTRIBUTE, () -> org.bukkit.Registry.ATTRIBUTE), + apiOnly(Registries.BANNER_PATTERN, RegistryKey.BANNER_PATTERN, () -> org.bukkit.Registry.BANNER_PATTERN), + apiOnly(Registries.CAT_VARIANT, RegistryKey.CAT_VARIANT, () -> org.bukkit.Registry.CAT_VARIANT), + apiOnly(Registries.ENTITY_TYPE, RegistryKey.ENTITY_TYPE, () -> org.bukkit.Registry.ENTITY_TYPE), + apiOnly(Registries.PARTICLE_TYPE, RegistryKey.PARTICLE_TYPE, () -> org.bukkit.Registry.PARTICLE_TYPE), + apiOnly(Registries.POTION, RegistryKey.POTION, () -> org.bukkit.Registry.POTION), + apiOnly(Registries.SOUND_EVENT, RegistryKey.SOUND_EVENT, () -> org.bukkit.Registry.SOUNDS), + apiOnly(Registries.VILLAGER_PROFESSION, RegistryKey.VILLAGER_PROFESSION, () -> org.bukkit.Registry.VILLAGER_PROFESSION), + apiOnly(Registries.VILLAGER_TYPE, RegistryKey.VILLAGER_TYPE, () -> org.bukkit.Registry.VILLAGER_TYPE), + apiOnly(Registries.MEMORY_MODULE_TYPE, RegistryKey.MEMORY_MODULE_TYPE, () -> (org.bukkit.Registry>) (org.bukkit.Registry) org.bukkit.Registry.MEMORY_MODULE_TYPE), + apiOnly(Registries.FLUID, RegistryKey.FLUID, () -> org.bukkit.Registry.FLUID), + apiOnly(Registries.FROG_VARIANT, RegistryKey.FROG_VARIANT, () -> org.bukkit.Registry.FROG_VARIANT), + apiOnly(Registries.MAP_DECORATION_TYPE, RegistryKey.MAP_DECORATION_TYPE, () -> org.bukkit.Registry.MAP_DECORATION_TYPE) + ); + final Map, RegistryEntry> byRegistryKey = new IdentityHashMap<>(REGISTRY_ENTRIES.size()); + final Map, RegistryEntry> byResourceKey = new IdentityHashMap<>(REGISTRY_ENTRIES.size()); + for (final RegistryEntry entry : REGISTRY_ENTRIES) { + byRegistryKey.put(entry.apiKey(), entry); + byResourceKey.put(entry.mcKey(), entry); + } + BY_REGISTRY_KEY = Collections.unmodifiableMap(byRegistryKey); + BY_RESOURCE_KEY = Collections.unmodifiableMap(byResourceKey); + } + + @SuppressWarnings("unchecked") + public static > @Nullable RegistryEntry getEntry(final ResourceKey> resourceKey) { + return (RegistryEntry) BY_RESOURCE_KEY.get(resourceKey); + } + + @SuppressWarnings("unchecked") + public static > @Nullable RegistryEntry getEntry(final RegistryKey registryKey) { + return (RegistryEntry) BY_REGISTRY_KEY.get(registryKey); + } + + 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..0000000000000000000000000000000000000000 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java @@ -0,0 +0,0 @@ +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, 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> getLoadedServerBackedRegistries() { + return this.registries.keySet().stream().filter(registryHolder -> !(PaperRegistries.getEntry(registryHolder) instanceof ApiRegistryEntry)).collect(Collectors.toUnmodifiableSet()); + } + + @SuppressWarnings("unchecked") + @Deprecated(forRemoval = true) + @Override + public @Nullable Registry getRegistry(final Class type) { + final RegistryKey registryKey; + final @Nullable RegistryEntry entry; + registryKey = requireNonNull(byType(type), () -> type + " is not a valid registry type"); + entry = PaperRegistries.getEntry(registryKey); + final @Nullable RegistryHolder registry = (RegistryHolder) 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) { + // 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 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 Registry getRegistry(final RegistryKey key) { + if (PaperRegistries.getEntry(key) == null) { + throw new NoSuchElementException(key + " is not a valid registry key"); + } + final @Nullable RegistryHolder registryHolder = (RegistryHolder) 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 Registry possiblyUnwrap(final Registry registry) { + if (registry instanceof final DelayedRegistry delayedRegistry) { // if not coming from legacy, unwrap the delayed registry + return delayedRegistry.delegate(); + } + return registry; + } + + public void registerReloadableRegistry(final ResourceKey> resourceKey, final net.minecraft.core.Registry registry) { + this.registerRegistry(resourceKey, registry, true); + } + + public void registerRegistry(final ResourceKey> resourceKey, final net.minecraft.core.Registry 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 > void registerRegistry(final ResourceKey> resourceKey, final net.minecraft.core.Registry registry, final boolean replace) { + final @Nullable RegistryEntry entry = PaperRegistries.getEntry(resourceKey); + if (entry == null) { // skip registries that don't have API entries + return; + } + final @Nullable RegistryHolder registryHolder = (RegistryHolder) 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 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) registryHolder).loadFrom(delayedEntry, registry); + } else { + throw new IllegalArgumentException(resourceKey + " has already been created"); + } + } + } + + @SuppressWarnings("unchecked") + @Deprecated + @VisibleForTesting + public static @Nullable RegistryKey byType(final Class type) { + return (RegistryKey) LegacyRegistryIdentifiers.CLASS_TO_KEY_MAP.get(type); + } +} 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..0000000000000000000000000000000000000000 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/RegistryHolder.java @@ -0,0 +0,0 @@ +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 { + + Registry get(); + + final class Memoized> implements RegistryHolder { + + private final Supplier memoizedSupplier; + + public Memoized(final Supplier supplier) { + this.memoizedSupplier = Suppliers.memoize(supplier::get); + } + + public Registry get() { + return this.memoizedSupplier.get(); + } + } + + final class Delayed> implements RegistryHolder { + + private final DelayedRegistry delayedRegistry = new DelayedRegistry<>(); + + @Override + public DelayedRegistry get() { + return this.delayedRegistry; + } + + void loadFrom(final DelayedRegistryEntry delayedEntry, final net.minecraft.core.Registry registry) { + final RegistryHolder delegateHolder = delayedEntry.delegate().createRegistryHolder(registry); + if (!(delegateHolder instanceof RegistryHolder.Memoized)) { + throw new IllegalArgumentException(delegateHolder + " must be a memoized holder"); + } + this.delayedRegistry.load(((Memoized) 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..0000000000000000000000000000000000000000 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/entry/ApiRegistryEntry.java @@ -0,0 +0,0 @@ +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 extends BaseRegistryEntry> { + + private final Supplier> registrySupplier; + + protected ApiRegistryEntry( + final ResourceKey> mcKey, + final RegistryKey apiKey, + final Supplier> registrySupplier + ) { + super(mcKey, apiKey); + this.registrySupplier = registrySupplier; + } + + @Override + public RegistryHolder createRegistryHolder(final Registry 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..0000000000000000000000000000000000000000 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/entry/BaseRegistryEntry.java @@ -0,0 +0,0 @@ +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> implements RegistryEntry { // TODO remove Keyed + + private final ResourceKey> minecraftRegistryKey; + private final RegistryKey apiRegistryKey; + + protected BaseRegistryEntry(final ResourceKey> minecraftRegistryKey, final RegistryKey apiRegistryKey) { + this.minecraftRegistryKey = minecraftRegistryKey; + this.apiRegistryKey = apiRegistryKey; + } + + @Override + public final ResourceKey> mcKey() { + return this.minecraftRegistryKey; + } + + @Override + public final RegistryKey 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..0000000000000000000000000000000000000000 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/entry/CraftRegistryEntry.java @@ -0,0 +0,0 @@ +package io.papermc.paper.registry.entry; + +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.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; + +@DefaultQualifier(NonNull.class) +public class CraftRegistryEntry extends BaseRegistryEntry> { // TODO remove Keyed + + protected final Class classToPreload; + protected final BiFunction minecraftToBukkit; + + protected CraftRegistryEntry( + final ResourceKey> mcKey, + final RegistryKey apiKey, + final Class classToPreload, + final BiFunction minecraftToBukkit + ) { + super(mcKey, apiKey); + this.classToPreload = classToPreload; + this.minecraftToBukkit = minecraftToBukkit; + } + + @Override + public RegistryHolder createRegistryHolder(final Registry nmsRegistry) { + return new RegistryHolder.Memoized<>(() -> this.createApiRegistry(nmsRegistry)); + } + + private CraftRegistry createApiRegistry(final Registry nmsRegistry) { + return new CraftRegistry<>(this.classToPreload, nmsRegistry, this.minecraftToBukkit); + } +} 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..0000000000000000000000000000000000000000 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/entry/RegistryEntry.java @@ -0,0 +0,0 @@ +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.CraftRegistry; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; + +@DefaultQualifier(NonNull.class) +public interface RegistryEntry> extends RegistryEntryInfo { // TODO remove Keyed + + RegistryHolder createRegistryHolder(Registry nmsRegistry); + + /** + * 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 delayed() { + return new DelayedRegistryEntry<>(this); + } + + static RegistryEntry> entry( + final ResourceKey> mcKey, + final RegistryKey apiKey, + final Class classToPreload, + final BiFunction minecraftToBukkit + ) { + return new CraftRegistryEntry<>(mcKey, apiKey, classToPreload, minecraftToBukkit); + } + + static RegistryEntry> apiOnly( + final ResourceKey> mcKey, + final RegistryKey apiKey, + final Supplier> 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..0000000000000000000000000000000000000000 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/entry/RegistryEntryInfo.java @@ -0,0 +0,0 @@ +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 { + + ResourceKey> mcKey(); + + RegistryKey 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..0000000000000000000000000000000000000000 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/entry/package-info.java @@ -0,0 +0,0 @@ +@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..0000000000000000000000000000000000000000 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistry.java @@ -0,0 +0,0 @@ +package io.papermc.paper.registry.legacy; + +import java.util.Iterator; +import java.util.function.Supplier; +import java.util.stream.Stream; +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> implements Registry { + + private @MonotonicNonNull Supplier delegate; + + public void load(final Supplier registry) { + if (this.delegate != null) { + throw new IllegalStateException("Registry already loaded!"); + } + this.delegate = registry; + } + + public Registry 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 Iterator iterator() { + return this.delegate().iterator(); + } + + @Override + public Stream 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..0000000000000000000000000000000000000000 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/legacy/DelayedRegistryEntry.java @@ -0,0 +0,0 @@ +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>(RegistryEntry delegate) implements RegistryEntry { + + @Override + public ResourceKey> mcKey() { + return this.delegate.mcKey(); + } + + @Override + public RegistryKey apiKey() { + return this.delegate.apiKey(); + } + + @Override + public RegistryHolder createRegistryHolder(final Registry 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..0000000000000000000000000000000000000000 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/legacy/LegacyRegistryIdentifiers.java @@ -0,0 +0,0 @@ +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, RegistryKey> CLASS_TO_KEY_MAP; + + static { + final ImmutableMap.Builder, 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..0000000000000000000000000000000000000000 --- /dev/null +++ b/src/main/java/io/papermc/paper/registry/legacy/package-info.java @@ -0,0 +0,0 @@ +@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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java +++ b/src/main/java/net/minecraft/core/registries/BuiltInRegistries.java @@ -0,0 +0,0 @@ public class BuiltInRegistries { ResourceKey> key, R registry, BuiltInRegistries.RegistryBootstrap initializer ) { Bootstrap.checkBootstrapCalled(() -> "registry " + key); + 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/resources/RegistryDataLoader.java +++ b/src/main/java/net/minecraft/resources/RegistryDataLoader.java @@ -0,0 +0,0 @@ public class RegistryDataLoader { public static record RegistryData(ResourceKey> key, Codec elementCodec) { RegistryDataLoader.Loader create(Lifecycle lifecycle, Map, Exception> errors) { WritableRegistry 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/ReloadableServerRegistries.java +++ b/src/main/java/net/minecraft/server/ReloadableServerRegistries.java @@ -0,0 +0,0 @@ public class ReloadableServerRegistries { return CompletableFuture.supplyAsync( () -> { WritableRegistry writableRegistry = new MappedRegistry<>(type.registryKey(), Lifecycle.experimental()); + io.papermc.paper.registry.PaperRegistryAccess.instance().registerReloadableRegistry(type.registryKey(), writableRegistry); // Paper - register reloadable registry Map map = new HashMap<>(); SimpleJsonResourceReloadListener.scanDirectory(resourceManager, type.directory(), GSON, map); map.forEach( diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java @@ -0,0 +0,0 @@ public class CraftRegistry implements Registry { + ", 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 Registry createRegistry(Class bukkitClass, RegistryAccess registryHolder) { - if (bukkitClass == Enchantment.class) { - return new CraftRegistry<>(Enchantment.class, registryHolder.registryOrThrow(Registries.ENCHANTMENT), CraftEnchantment::new); - } - if (bukkitClass == GameEvent.class) { - return new CraftRegistry<>(GameEvent.class, registryHolder.registryOrThrow(Registries.GAME_EVENT), CraftGameEvent::new); - } - if (bukkitClass == MusicInstrument.class) { - return new CraftRegistry<>(MusicInstrument.class, registryHolder.registryOrThrow(Registries.INSTRUMENT), CraftMusicInstrument::new); - } - if (bukkitClass == PotionEffectType.class) { - return new CraftRegistry<>(PotionEffectType.class, registryHolder.registryOrThrow(Registries.MOB_EFFECT), CraftPotionEffectType::new); - } - if (bukkitClass == Structure.class) { - return new CraftRegistry<>(Structure.class, registryHolder.registryOrThrow(Registries.STRUCTURE), CraftStructure::new); - } - if (bukkitClass == StructureType.class) { - return new CraftRegistry<>(StructureType.class, BuiltInRegistries.STRUCTURE_TYPE, CraftStructureType::new); - } - if (bukkitClass == TrimMaterial.class) { - return new CraftRegistry<>(TrimMaterial.class, registryHolder.registryOrThrow(Registries.TRIM_MATERIAL), CraftTrimMaterial::new); - } - if (bukkitClass == TrimPattern.class) { - return new CraftRegistry<>(TrimPattern.class, registryHolder.registryOrThrow(Registries.TRIM_PATTERN), CraftTrimPattern::new); - } - if (bukkitClass == DamageType.class) { - return new CraftRegistry<>(DamageType.class, registryHolder.registryOrThrow(Registries.DAMAGE_TYPE), CraftDamageType::new); - } - if (bukkitClass == Wolf.Variant.class) { - return new CraftRegistry<>(Wolf.Variant.class, registryHolder.registryOrThrow(Registries.WOLF_VARIANT), CraftWolf.CraftVariant::new); - } - - return null; - } + // Paper - move to PaperRegistries - private final Class bukkitClass; + private final Class bukkitClass; // Paper - relax preload class private final Map cache = new HashMap<>(); private final net.minecraft.core.Registry minecraftRegistry; private final BiFunction minecraftToBukkit; private boolean init; - public CraftRegistry(Class bukkitClass, net.minecraft.core.Registry minecraftRegistry, BiFunction minecraftToBukkit) { + public CraftRegistry(Class bukkitClass, net.minecraft.core.Registry minecraftRegistry, BiFunction minecraftToBukkit) { // Paper - relax preload class this.bukkitClass = bukkitClass; this.minecraftRegistry = minecraftRegistry; this.minecraftToBukkit = minecraftToBukkit; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -0,0 +0,0 @@ public final class CraftServer implements Server { protected final DedicatedServer console; protected final DedicatedPlayerList playerList; private final Map worlds = new LinkedHashMap(); - private final Map, Registry> registries = new HashMap<>(); + // private final Map, Registry> registries = new HashMap<>(); // Paper - replace with RegistryAccess private YamlConfiguration configuration; private YamlConfiguration commandsConfiguration; private final Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions())); @@ -0,0 +0,0 @@ public final class CraftServer implements Server { @Override public Registry getRegistry(Class aClass) { - return (Registry) 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/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..0000000000000000000000000000000000000000 --- /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/test/java/io/papermc/paper/registry/LegacyRegistryIdentifierTest.java b/src/test/java/io/papermc/paper/registry/LegacyRegistryIdentifierTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 --- /dev/null +++ b/src/test/java/io/papermc/paper/registry/LegacyRegistryIdentifierTest.java @@ -0,0 +0,0 @@ +package io.papermc.paper.registry; + +import org.bukkit.GameEvent; +import org.bukkit.MusicInstrument; +import org.bukkit.inventory.meta.trim.TrimPattern; +import org.bukkit.support.AbstractTestingBase; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertSame; + +@Deprecated +class LegacyRegistryIdentifierTest extends AbstractTestingBase { + + @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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/test/java/io/papermc/paper/registry/RegistryKeyTest.java +++ b/src/test/java/io/papermc/paper/registry/RegistryKeyTest.java @@ -0,0 +0,0 @@ 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.Keyed; import org.bukkit.support.AbstractTestingBase; 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; class RegistryKeyTest extends AbstractTestingBase { @@ -0,0 +0,0 @@ class RegistryKeyTest extends AbstractTestingBase { void testApiRegistryKeysExist(final RegistryKey key) { final Optional> registry = AbstractTestingBase.REGISTRY_CUSTOM.registry(ResourceKey.createRegistryKey(new ResourceLocation(key.key().asString()))); assertTrue(registry.isPresent(), "Missing vanilla registry for " + key.key().asString()); + } + @ParameterizedTest + @MethodSource("data") + void testRegistryEntryExists(final RegistryKey key) { + final 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java +++ b/src/test/java/org/bukkit/registry/RegistryArgumentAddedTest.java @@ -0,0 +0,0 @@ public class RegistryArgumentAddedTest extends AbstractTestingBase { // Make sure every registry is created Class.forName(Registry.class.getName()); - Set> loadedRegistries = new HashSet<>(DummyServer.registers.keySet()); - Set> notFound = new HashSet<>(); + // Paper start + Set> loadedRegistries = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>()); + loadedRegistries.addAll(io.papermc.paper.registry.PaperRegistryAccess.instance().getLoadedServerBackedRegistries()); + // Paper end + Set> 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/test/java/org/bukkit/registry/RegistryConversionTest.java +++ b/src/test/java/org/bukkit/registry/RegistryConversionTest.java @@ -0,0 +0,0 @@ public class RegistryConversionTest extends AbstractTestingBase { @Order(1) @RegistriesTest - public void testHandleableImplementation(Class clazz) { + public void testHandleableImplementation(io.papermc.paper.registry.RegistryKey type, Class clazz) { // Paper Set> notImplemented = new HashSet<>(); - Registry registry = Bukkit.getRegistry(clazz); + Registry registry = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(type); // Paper for (Keyed item : registry) { if (!(item instanceof Handleable)) { @@ -0,0 +0,0 @@ public class RegistryConversionTest extends AbstractTestingBase { @Order(2) @RegistriesTest - public void testMinecraftToBukkitPresent(Class clazz, ResourceKey> registryKey, + public void testMinecraftToBukkitPresent(io.papermc.paper.registry.RegistryKey type, Class clazz, ResourceKey> registryKey, // Paper Class craftClazz, Class minecraftClazz) { Method method = null; try { @@ -0,0 +0,0 @@ public class RegistryConversionTest extends AbstractTestingBase { @Order(2) @RegistriesTest - public void testBukkitToMinecraftPresent(Class clazz, ResourceKey> registryKey, + public void testBukkitToMinecraftPresent(io.papermc.paper.registry.RegistryKey type, Class clazz, ResourceKey> registryKey, // Paper Class craftClazz, Class minecraftClazz) { Method method = null; try { @@ -0,0 +0,0 @@ public class RegistryConversionTest extends AbstractTestingBase { """, minecraftClazz.getName(), clazz.getSimpleName()); } - @Order(2) + @Order(3) @RegistriesTest - public void testMinecraftToBukkitNullValue(Class clazz) throws IllegalAccessException { + public void testMinecraftToBukkitNullValue(io.papermc.paper.registry.RegistryKey type, Class clazz) throws IllegalAccessException { // Paper this.checkValidMinecraftToBukkit(clazz); try { @@ -0,0 +0,0 @@ public class RegistryConversionTest extends AbstractTestingBase { @Order(3) @RegistriesTest - public void testBukkitToMinecraftNullValue(Class clazz) throws IllegalAccessException { + public void testBukkitToMinecraftNullValue(io.papermc.paper.registry.RegistryKey type, Class clazz) throws IllegalAccessException { // Paper this.checkValidBukkitToMinecraft(clazz); try { @@ -0,0 +0,0 @@ public class RegistryConversionTest extends AbstractTestingBase { @Order(3) @RegistriesTest - public void testMinecraftToBukkit(Class clazz) { + public void testMinecraftToBukkit(io.papermc.paper.registry.RegistryKey type, Class clazz) { // Paper this.checkValidMinecraftToBukkit(clazz); this.checkValidHandle(clazz); Map 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]; @@ -0,0 +0,0 @@ public class RegistryConversionTest extends AbstractTestingBase { @Order(3) @RegistriesTest - public void testBukkitToMinecraft(Class clazz) { + public void testBukkitToMinecraft(io.papermc.paper.registry.RegistryKey type, Class clazz) { // Paper this.checkValidBukkitToMinecraft(clazz); this.checkValidHandle(clazz); Map 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]; @@ -0,0 +0,0 @@ public class RegistryConversionTest extends AbstractTestingBase { */ @Order(3) @RegistriesTest - public void testMinecraftToBukkitNoValidMinecraft(Class clazz, ResourceKey> registryKey, + public void testMinecraftToBukkitNoValidMinecraft(io.papermc.paper.registry.RegistryKey type, Class clazz, ResourceKey> registryKey, // Paper Class craftClazz, Class minecraftClazz) throws IllegalAccessException { this.checkValidMinecraftToBukkit(clazz); diff --git a/src/test/java/org/bukkit/support/DummyServer.java b/src/test/java/org/bukkit/support/DummyServer.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/test/java/org/bukkit/support/DummyServer.java +++ b/src/test/java/org/bukkit/support/DummyServer.java @@ -0,0 +0,0 @@ public final class DummyServer { when(instance.getLootTable(any())).then(mock -> new CraftLootTable(mock.getArgument(0), AbstractTestingBase.DATA_PACK.fullRegistries().getLootTable(ResourceKey.create(Registries.LOOT_TABLE, CraftNamespacedKey.toMinecraft(mock.getArgument(0)))))); - when(instance.getRegistry(any())).then((Answer>) mock -> { - Class aClass = mock.getArgument(0); - return registers.computeIfAbsent(aClass, key -> CraftRegistry.createRegistry(aClass, AbstractTestingBase.REGISTRY_CUSTOM)); - }); + // Paper - RegistryAccess // Paper start - testing additions final Thread currentThread = Thread.currentThread(); diff --git a/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java b/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java +++ b/src/test/java/org/bukkit/support/provider/RegistriesArgumentProvider.java @@ -0,0 +0,0 @@ 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; @@ -0,0 +0,0 @@ public class RegistriesArgumentProvider implements ArgumentsProvider { static { // Order: Bukkit class, Minecraft Registry key, CraftBukkit class, Minecraft class - DATA.add(Arguments.of(Enchantment.class, Registries.ENCHANTMENT, CraftEnchantment.class, net.minecraft.world.item.enchantment.Enchantment.class)); - DATA.add(Arguments.of(GameEvent.class, Registries.GAME_EVENT, CraftGameEvent.class, net.minecraft.world.level.gameevent.GameEvent.class)); - DATA.add(Arguments.of(MusicInstrument.class, Registries.INSTRUMENT, CraftMusicInstrument.class, Instrument.class)); - DATA.add(Arguments.of(PotionEffectType.class, Registries.MOB_EFFECT, CraftPotionEffectType.class, MobEffect.class)); - DATA.add(Arguments.of(Structure.class, Registries.STRUCTURE, CraftStructure.class, net.minecraft.world.level.levelgen.structure.Structure.class)); - DATA.add(Arguments.of(StructureType.class, Registries.STRUCTURE_TYPE, CraftStructureType.class, net.minecraft.world.level.levelgen.structure.StructureType.class)); - DATA.add(Arguments.of(TrimMaterial.class, Registries.TRIM_MATERIAL, CraftTrimMaterial.class, net.minecraft.world.item.armortrim.TrimMaterial.class)); - DATA.add(Arguments.of(TrimPattern.class, Registries.TRIM_PATTERN, CraftTrimPattern.class, net.minecraft.world.item.armortrim.TrimPattern.class)); - DATA.add(Arguments.of(DamageType.class, Registries.DAMAGE_TYPE, CraftDamageType.class, net.minecraft.world.damagesource.DamageType.class)); - DATA.add(Arguments.of(Wolf.Variant.class, Registries.WOLF_VARIANT, CraftWolf.CraftVariant.class, WolfVariant.class)); + // Order: RegistryKey, Bukkit class, Minecraft Registry key, CraftBukkit class, Minecraft class + DATA.add(Arguments.of(RegistryKey.ENCHANTMENT, Enchantment.class, Registries.ENCHANTMENT, CraftEnchantment.class, net.minecraft.world.item.enchantment.Enchantment.class)); + DATA.add(Arguments.of(RegistryKey.GAME_EVENT, GameEvent.class, Registries.GAME_EVENT, CraftGameEvent.class, net.minecraft.world.level.gameevent.GameEvent.class)); + DATA.add(Arguments.of(RegistryKey.INSTRUMENT, MusicInstrument.class, Registries.INSTRUMENT, CraftMusicInstrument.class, Instrument.class)); + DATA.add(Arguments.of(RegistryKey.MOB_EFFECT, PotionEffectType.class, Registries.MOB_EFFECT, CraftPotionEffectType.class, MobEffect.class)); + DATA.add(Arguments.of(RegistryKey.STRUCTURE, Structure.class, Registries.STRUCTURE, CraftStructure.class, net.minecraft.world.level.levelgen.structure.Structure.class)); + DATA.add(Arguments.of(RegistryKey.STRUCTURE_TYPE, StructureType.class, Registries.STRUCTURE_TYPE, CraftStructureType.class, net.minecraft.world.level.levelgen.structure.StructureType.class)); + DATA.add(Arguments.of(RegistryKey.TRIM_MATERIAL, TrimMaterial.class, Registries.TRIM_MATERIAL, CraftTrimMaterial.class, net.minecraft.world.item.armortrim.TrimMaterial.class)); + DATA.add(Arguments.of(RegistryKey.TRIM_PATTERN, TrimPattern.class, Registries.TRIM_PATTERN, CraftTrimPattern.class, net.minecraft.world.item.armortrim.TrimPattern.class)); + DATA.add(Arguments.of(RegistryKey.DAMAGE_TYPE, DamageType.class, Registries.DAMAGE_TYPE, CraftDamageType.class, net.minecraft.world.damagesource.DamageType.class)); + DATA.add(Arguments.of(RegistryKey.WOLF_VARIANT, Wolf.Variant.class, Registries.WOLF_VARIANT, CraftWolf.CraftVariant.class, net.minecraft.world.entity.animal.WolfVariant.class)); } @Override diff --git a/src/test/java/org/bukkit/support/provider/RegistryArgumentProvider.java b/src/test/java/org/bukkit/support/provider/RegistryArgumentProvider.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/test/java/org/bukkit/support/provider/RegistryArgumentProvider.java +++ b/src/test/java/org/bukkit/support/provider/RegistryArgumentProvider.java @@ -0,0 +0,0 @@ public class RegistryArgumentProvider implements ArgumentsProvider, AnnotationCo @Override public Stream 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 getValues(Class registryType) { - Registry registry = Bukkit.getRegistry(registryType); + public static Stream getValues(io.papermc.paper.registry.RegistryKey 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())); }