Handle disabled vanilla registry values correctly (#11781)
This commit is contained in:
@@ -6,12 +6,15 @@ import io.papermc.paper.registry.set.NamedRegistryKeySetImpl;
|
||||
import io.papermc.paper.registry.tag.Tag;
|
||||
import io.papermc.paper.util.Holderable;
|
||||
import java.util.Collection;
|
||||
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.resources.ResourceKey;
|
||||
import org.bukkit.Keyed;
|
||||
@@ -162,7 +165,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
|
||||
@@ -177,6 +181,22 @@ 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 void lockReferenceHolders() {
|
||||
Preconditions.checkState(this.cache.isEmpty(), "Registry %s is already loaded", this.minecraftRegistry.key());
|
||||
|
||||
try {
|
||||
Class.forName(this.bukkitClass.getName()); // this should always trigger the initialization of the class
|
||||
} catch (final ClassNotFoundException e) {
|
||||
throw new IllegalStateException("Failed to load class " + this.bukkitClass.getSimpleName(), e);
|
||||
}
|
||||
if (!this.minecraftToBukkit.supportsDirectHolders()) {
|
||||
return;
|
||||
}
|
||||
Preconditions.checkState(!this.lockReferenceHolders, "Reference holders are already locked");
|
||||
this.lockReferenceHolders = true;
|
||||
}
|
||||
|
||||
// Paper - inline into CraftRegistry#get(Registry, NamespacedKey, ApiVersion) above
|
||||
@@ -188,28 +208,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;
|
||||
}
|
||||
@@ -285,4 +296,7 @@ public class CraftRegistry<B extends Keyed, M> implements Registry<B> {
|
||||
return this.minecraftRegistry.getTags().<Tag<B>>map(NamedRegistryKeySetImpl::new).toList();
|
||||
}
|
||||
// Paper end - RegistrySet API
|
||||
|
||||
final class InvalidHolderOwner implements HolderOwner<M> {
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user