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
This commit is contained in:
Jake Potrebic
2023-02-27 18:28:39 -08:00
parent 23b8639dbf
commit 239e7a6b37
38 changed files with 930 additions and 214 deletions

View File

@@ -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));
}
}

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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());
}

View File

@@ -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());
}

View File

@@ -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());
}

View File

@@ -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());
}

View File

@@ -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

View File

@@ -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()));
}