aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJake Potrebic <[email protected]>2024-12-22 22:04:51 -0800
committerJake Potrebic <[email protected]>2024-12-23 14:50:02 -0800
commit957f493566248c2fd721bed6219d4ed163bc809d (patch)
treed02ecea14eeaf37463467d66fd645d495e0ee188
parentaa2c52baac16acfd3fea91be648587819042554b (diff)
downloadPaper-957f493566248c2fd721bed6219d4ed163bc809d.tar.gz
Paper-957f493566248c2fd721bed6219d4ed163bc809d.zip
Handle disabled vanilla registry values correctly
-rw-r--r--paper-server/patches/sources/net/minecraft/core/registries/BuiltInRegistries.java.patch8
-rw-r--r--paper-server/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java17
-rw-r--r--paper-server/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java95
-rw-r--r--paper-server/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java31
4 files changed, 65 insertions, 86 deletions
diff --git a/paper-server/patches/sources/net/minecraft/core/registries/BuiltInRegistries.java.patch b/paper-server/patches/sources/net/minecraft/core/registries/BuiltInRegistries.java.patch
index bc224c349b..0d1d444e1b 100644
--- a/paper-server/patches/sources/net/minecraft/core/registries/BuiltInRegistries.java.patch
+++ b/paper-server/patches/sources/net/minecraft/core/registries/BuiltInRegistries.java.patch
@@ -41,6 +41,14 @@
freeze();
validate(REGISTRY);
}
+@@ -338,6 +_,7 @@
+ if (supplier.get() == null) {
+ LOGGER.error("Unable to bootstrap registry '{}'", resourceLocation);
+ }
++ io.papermc.paper.registry.PaperRegistryAccess.instance().lockReferenceHolders(ResourceKey.createRegistryKey(resourceLocation)); // Paper - lock reference holder creation
+ });
+ }
+
@@ -346,6 +_,7 @@
for (Registry<?> registry : REGISTRY) {
diff --git a/paper-server/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java b/paper-server/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java
index 3be7e0a1fb..6400df6ea1 100644
--- a/paper-server/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java
+++ b/paper-server/src/main/java/io/papermc/paper/registry/PaperRegistryAccess.java
@@ -1,5 +1,6 @@
package io.papermc.paper.registry;
+import com.google.common.base.Preconditions;
import io.papermc.paper.registry.entry.RegistryEntry;
import io.papermc.paper.registry.entry.RegistryEntryMeta;
import io.papermc.paper.registry.legacy.DelayedRegistry;
@@ -13,6 +14,7 @@ import java.util.stream.Collectors;
import net.minecraft.resources.ResourceKey;
import org.bukkit.Keyed;
import org.bukkit.Registry;
+import org.bukkit.craftbukkit.CraftRegistry;
import org.jetbrains.annotations.VisibleForTesting;
import org.jspecify.annotations.Nullable;
@@ -104,6 +106,21 @@ public class PaperRegistryAccess implements RegistryAccess {
this.registerRegistry(resourceKey, registry, false);
}
+ public <M> void lockReferenceHolders(final ResourceKey<? extends net.minecraft.core.Registry<M>> resourceKey) {
+ final RegistryEntry<M, Keyed> entry = PaperRegistries.getEntry(resourceKey);
+ if (entry == null || !(entry.meta() instanceof final RegistryEntryMeta.ServerSide<M, Keyed> serverSide) || !serverSide.registryTypeMapper().supportsDirectHolders()) {
+ return;
+ }
+ final CraftRegistry<?, M> registry = (CraftRegistry<?, M>) this.getRegistry(entry.apiKey());
+ Preconditions.checkState(registry.isUnloaded(), "Registry %s is already loaded", resourceKey);
+ try {
+ Class.forName(serverSide.classToPreload().getName()); // this should always trigger the initialization of the class
+ } catch (final ClassNotFoundException e) {
+ throw new IllegalStateException("Failed to load class " + serverSide.classToPreload().getName(), e);
+ }
+ registry.lockReferenceHolders();
+ }
+
@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);
diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
index 332215f8b4..ab0a1eed5c 100644
--- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
+++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftRegistry.java
@@ -3,66 +3,26 @@ package org.bukkit.craftbukkit;
import com.google.common.base.Preconditions;
import io.papermc.paper.registry.entry.RegistryEntryMeta;
import io.papermc.paper.util.Holderable;
+import io.papermc.paper.util.MCUtil;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.Optional;
import java.util.function.BiFunction;
import java.util.stream.Stream;
import net.minecraft.core.Holder;
+import net.minecraft.core.HolderOwner;
import net.minecraft.core.RegistryAccess;
-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.NamespacedKey;
import org.bukkit.Particle;
import org.bukkit.Registry;
-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.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.ApiVersion;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.craftbukkit.util.Handleable;
-import org.bukkit.damage.DamageType;
-import org.bukkit.enchantments.Enchantment;
-import org.bukkit.entity.Cat;
import org.bukkit.entity.EntityType;
-import org.bukkit.entity.Frog;
-import org.bukkit.entity.Villager;
-import org.bukkit.entity.Wolf;
-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.jetbrains.annotations.NotNull;
public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
@@ -202,7 +162,8 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
private final net.minecraft.core.Registry<M> minecraftRegistry;
private final io.papermc.paper.registry.entry.RegistryTypeMapper<M, B> minecraftToBukkit; // Paper - switch to Holder
private final BiFunction<NamespacedKey, ApiVersion, NamespacedKey> serializationUpdater; // Paper - rename to make it *clear* what it is *only* for
- private boolean init;
+ private final InvalidHolderOwner invalidHolderOwner = new InvalidHolderOwner();
+ private boolean lockReferenceHolders;
public CraftRegistry(Class<?> bukkitClass, net.minecraft.core.Registry<M> minecraftRegistry, BiFunction<? super NamespacedKey, M, B> minecraftToBukkit, BiFunction<NamespacedKey, ApiVersion, NamespacedKey> serializationUpdater) { // Paper - relax preload class
// Paper start - switch to Holder
@@ -217,6 +178,16 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
this.minecraftRegistry = minecraftRegistry;
this.minecraftToBukkit = minecraftToBukkit;
this.serializationUpdater = serializationUpdater;
+ this.lockReferenceHolders = !this.minecraftToBukkit.supportsDirectHolders();
+ }
+
+ public boolean isUnloaded() {
+ return this.cache.isEmpty();
+ }
+
+ public void lockReferenceHolders() {
+ Preconditions.checkState(!this.lockReferenceHolders, "Reference holders are already locked");
+ this.lockReferenceHolders = true;
}
// Paper - inline into CraftRegistry#get(Registry, NamespacedKey, ApiVersion) above
@@ -228,28 +199,19 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
return cached;
}
- // Make sure that the bukkit class is loaded before creating an instance.
- // This ensures that only one instance with a given key is created.
- //
- // Without this code (when bukkit class is not loaded):
- // Registry#get -> #createBukkit -> (load class -> create default) -> put in cache
- // Result: Registry#get != <bukkitClass>.<field> for possible one registry item
- //
- // With this code (when bukkit class is not loaded):
- // Registry#get -> (load class -> create default) -> Registry#get -> get from cache
- // Result: Registry#get == <bukkitClass>.<field>
- if (!this.init) {
- this.init = true;
- try {
- Class.forName(this.bukkitClass.getName());
- } catch (ClassNotFoundException e) {
- throw new RuntimeException("Could not load registry class " + this.bukkitClass, e);
- }
-
- return this.get(namespacedKey);
+ final Optional<Holder.Reference<M>> holderOptional = this.minecraftRegistry.get(CraftNamespacedKey.toMinecraft(namespacedKey));
+ final Holder.Reference<M> holder;
+ if (holderOptional.isPresent()) {
+ holder = holderOptional.get();
+ } else if (!this.lockReferenceHolders && this.minecraftToBukkit.supportsDirectHolders()) { // only works if its Holderable
+ // we lock the reference holders after the preload class has been initialized
+ // this is to support the vanilla mechanic of preventing vanilla registry entries being loaded. We need
+ // to create something to fill the API constant fields, so we create a dummy reference holder.
+ holder = Holder.Reference.createStandAlone(this.invalidHolderOwner, MCUtil.toResourceKey(this.minecraftRegistry.key(), namespacedKey));
+ } else {
+ holder = null;
}
-
- B bukkit = this.createBukkit(namespacedKey, this.minecraftRegistry.get(CraftNamespacedKey.toMinecraft(namespacedKey)).orElse(null)); // Paper - switch to Holder
+ final B bukkit = this.createBukkit(namespacedKey, holder);
if (bukkit == null) {
return null;
}
@@ -320,4 +282,7 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
return new io.papermc.paper.registry.set.NamedRegistryKeySetImpl<>(key, namedHolderSet);
}
// Paper end - RegistrySet API
+
+ final class InvalidHolderOwner implements HolderOwner<M> {
+ }
}
diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/paper-server/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java
index 34934f0dbe..36825fb8f0 100644
--- a/paper-server/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java
+++ b/paper-server/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java
@@ -1,11 +1,11 @@
package org.bukkit.craftbukkit.enchantments;
import com.google.common.base.Preconditions;
+import io.papermc.paper.util.Holderable;
import java.util.Locale;
import net.minecraft.Util;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.Registries;
-import net.minecraft.network.chat.contents.TranslatableContents;
import net.minecraft.tags.EnchantmentTags;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
@@ -13,13 +13,12 @@ import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.legacy.FieldRename;
import org.bukkit.craftbukkit.util.ApiVersion;
-import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.enchantments.EnchantmentTarget;
import org.bukkit.enchantments.EnchantmentWrapper;
import org.bukkit.inventory.ItemStack;
-public class CraftEnchantment extends Enchantment implements Handleable<net.minecraft.world.item.enchantment.Enchantment> {
+public class CraftEnchantment extends Enchantment implements Holderable<net.minecraft.world.item.enchantment.Enchantment> {
public static Enchantment minecraftToBukkit(net.minecraft.world.item.enchantment.Enchantment minecraft) {
return CraftRegistry.minecraftToBukkit(minecraft, Registries.ENCHANTMENT, Registry.ENCHANTMENT);
@@ -56,22 +55,20 @@ public class CraftEnchantment extends Enchantment implements Handleable<net.mine
return CraftRegistry.get(Registry.ENCHANTMENT, key, ApiVersion.CURRENT);
}
- private final NamespacedKey key;
private final Holder<net.minecraft.world.item.enchantment.Enchantment> handle;
- public CraftEnchantment(NamespacedKey key, net.minecraft.world.item.enchantment.Enchantment handle) {
- this.key = key;
- this.handle = CraftRegistry.getMinecraftRegistry(Registries.ENCHANTMENT).wrapAsHolder(handle);
+ public CraftEnchantment(Holder<net.minecraft.world.item.enchantment.Enchantment> holder) {
+ this.handle = holder;
}
@Override
- public net.minecraft.world.item.enchantment.Enchantment getHandle() {
- return this.handle.value();
+ public Holder<net.minecraft.world.item.enchantment.Enchantment> getHolder() {
+ return this.handle;
}
@Override
public NamespacedKey getKey() {
- return this.key;
+ return Holderable.super.getKey();
}
@Override
@@ -251,24 +248,16 @@ public class CraftEnchantment extends Enchantment implements Handleable<net.mine
@Override
public boolean equals(Object other) {
- if (this == other) {
- return true;
- }
-
- if (!(other instanceof CraftEnchantment)) {
- return false;
- }
-
- return this.getKey().equals(((Enchantment) other).getKey());
+ return Holderable.super.implEquals(other);
}
@Override
public int hashCode() {
- return this.getKey().hashCode();
+ return Holderable.super.implHashCode();
}
@Override
public String toString() {
- return "CraftEnchantment[" + this.getKey() + "]";
+ return Holderable.super.implToString();
}
}