Make RegistryObject.getHolder lazy, Should help cases where vanilla registries use holders from other vanilla registries. Closes #9961

This commit is contained in:
LexManos committed 2024-05-12 10:53:10 -07:00
1 parent dffa3dd4c9
commit c700b4ea9d
4 files changed
+68 -94

No files matched your search

@@ -377,7 +377,8 @@ class NamespacedWrapper<T> extends MappedRegistry<T> implements ILockableRegistr
return this.frozen;
}
boolean isIntrusive() {
@Override
public boolean isIntrusive() {
return this.intrusiveHolderCallback != null && this.stage == RegistryManager.ACTIVE;
}
@@ -22,8 +22,7 @@ import org.slf4j.Logger;
/**
* Register new registries when you receive this event through {@link RegistryBuilder} and {@link #create(RegistryBuilder)}.
*/
public class NewRegistryEvent extends Event implements IModBusEvent
{
public class NewRegistryEvent extends Event implements IModBusEvent {
private static final Logger LOGGER = LogUtils.getLogger();
private final List<RegistryData<?>> registries = new ArrayList<>();
@@ -35,8 +34,7 @@ public class NewRegistryEvent extends Event implements IModBusEvent
* @param builder The builder to turn into a {@link IForgeRegistry}
* @return A supplier of the {@link IForgeRegistry} created by the builder. Resolving too early will return null.
*/
public <V> Supplier<IForgeRegistry<V>> create(RegistryBuilder<V> builder)
{
public <V> Supplier<IForgeRegistry<V>> create(RegistryBuilder<V> builder) {
return create(builder, null);
}
@@ -47,8 +45,7 @@ public class NewRegistryEvent extends Event implements IModBusEvent
* @param onFill Called when the returned supplier is filled with the registry
* @return a supplier of the {@link IForgeRegistry} created by the builder. Resolving too early will return null.
*/
public <V> Supplier<IForgeRegistry<V>> create(RegistryBuilder<V> builder, @Nullable Consumer<IForgeRegistry<V>> onFill)
{
public <V> Supplier<IForgeRegistry<V>> create(RegistryBuilder<V> builder, @Nullable Consumer<IForgeRegistry<V>> onFill) {
RegistryHolder<V> registryHolder = new RegistryHolder<>();
registries.add(new RegistryData<>(builder, registryHolder, onFill));
@@ -57,20 +54,17 @@ public class NewRegistryEvent extends Event implements IModBusEvent
}
@SuppressWarnings("deprecation")
void fill()
{
void fill() {
RuntimeException aggregate = new RuntimeException();
Map<RegistryBuilder<?>, IForgeRegistry<?>> builtRegistries = new IdentityHashMap<>();
if (BuiltInRegistries.REGISTRY instanceof MappedRegistry<?> rootRegistry)
rootRegistry.unfreeze();
for (RegistryData<?> data : this.registries)
{
for (RegistryData<?> data : this.registries) {
try {
buildRegistry(builtRegistries, data);
} catch (Throwable t)
{
} catch (Throwable t) {
aggregate.addSuppressed(t);
return;
}
@@ -83,8 +77,7 @@ public class NewRegistryEvent extends Event implements IModBusEvent
LOGGER.error(LogUtils.FATAL_MARKER, "Failed to create some forge registries, see suppressed exceptions for details", aggregate);
}
private <T> void buildRegistry(Map<RegistryBuilder<?>, IForgeRegistry<?>> builtRegistries, RegistryData<T> data)
{
private <T> void buildRegistry(Map<RegistryBuilder<?>, IForgeRegistry<?>> builtRegistries, RegistryData<T> data) {
RegistryBuilder<T> builder = data.builder;
IForgeRegistry<T> registry = builder.create();
@@ -104,20 +97,17 @@ public class NewRegistryEvent extends Event implements IModBusEvent
Consumer<IForgeRegistry<V>> onFill
) {}
private static class RegistryHolder<V> implements Supplier<IForgeRegistry<V>>
{
private static class RegistryHolder<V> implements Supplier<IForgeRegistry<V>> {
IForgeRegistry<V> registry = null;
@Override
public IForgeRegistry<V> get()
{
public IForgeRegistry<V> get() {
return this.registry;
}
}
@Override
public String toString()
{
public String toString() {
return "RegistryEvent.NewRegistry";
}
}
@@ -6,6 +6,7 @@
package net.minecraftforge.registries;
import net.minecraft.core.Holder;
import net.minecraft.core.MappedRegistry;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceKey;
@@ -21,8 +22,7 @@ import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;
public final class RegistryObject<T> implements Supplier<T>
{
public final class RegistryObject<T> implements Supplier<T> {
@Nullable
private final ResourceLocation name;
@Nullable
@@ -31,7 +31,7 @@ public final class RegistryObject<T> implements Supplier<T>
@Nullable
private T value;
@Nullable
private Holder<T> holder;
private Supplier<Holder<T>> holder;
/**
* Factory for a {@link RegistryObject} that stores the value of an object from the provided forge registry once it is ready.
@@ -40,8 +40,7 @@ public final class RegistryObject<T> implements Supplier<T>
* @param registry the forge registry
* @return a {@link RegistryObject} that stores the value of an object from the provided forge registry once it is ready
*/
public static <T, U extends T> RegistryObject<U> create(final ResourceLocation name, IForgeRegistry<T> registry)
{
public static <T, U extends T> RegistryObject<U> create(final ResourceLocation name, IForgeRegistry<T> registry) {
return new RegistryObject<U>(name, registry);
}
@@ -59,8 +58,7 @@ public final class RegistryObject<T> implements Supplier<T>
* @see #create(ResourceLocation, IForgeRegistry)
* @see #create(ResourceLocation, ResourceLocation, String)
*/
public static <T, U extends T> RegistryObject<U> create(final ResourceLocation name, final ResourceKey<? extends Registry<T>> registryKey, String modid)
{
public static <T, U extends T> RegistryObject<U> create(final ResourceLocation name, final ResourceKey<? extends Registry<T>> registryKey, String modid) {
return new RegistryObject<>(name, registryKey.location(), modid, false);
}
@@ -79,9 +77,7 @@ public final class RegistryObject<T> implements Supplier<T>
* @see #create(ResourceLocation, IForgeRegistry)
* @see #create(ResourceLocation, ResourceLocation, String)
*/
public static <T, U extends T> RegistryObject<U> createOptional(final ResourceLocation name, final ResourceKey<? extends Registry<T>> registryKey,
String modid)
{
public static <T, U extends T> RegistryObject<U> createOptional(final ResourceLocation name, final ResourceKey<? extends Registry<T>> registryKey, String modid) {
return new RegistryObject<>(name, registryKey.location(), modid, true);
}
@@ -99,8 +95,7 @@ public final class RegistryObject<T> implements Supplier<T>
* @see #create(ResourceLocation, IForgeRegistry)
* @see #create(ResourceLocation, ResourceKey, String)
*/
public static <T, U extends T> RegistryObject<U> create(final ResourceLocation name, final ResourceLocation registryName, String modid)
{
public static <T, U extends T> RegistryObject<U> create(final ResourceLocation name, final ResourceLocation registryName, String modid) {
return new RegistryObject<>(name, registryName, modid, false);
}
@@ -119,8 +114,7 @@ public final class RegistryObject<T> implements Supplier<T>
* @see #create(ResourceLocation, IForgeRegistry)
* @see #create(ResourceLocation, ResourceKey, String)
*/
public static <T, U extends T> RegistryObject<U> createOptional(final ResourceLocation name, final ResourceLocation registryName, String modid)
{
public static <T, U extends T> RegistryObject<U> createOptional(final ResourceLocation name, final ResourceLocation registryName, String modid) {
return new RegistryObject<>(name, registryName, modid, true);
}
@@ -139,47 +133,41 @@ public final class RegistryObject<T> implements Supplier<T>
}
@SuppressWarnings("unchecked")
private RegistryObject(ResourceLocation name, IForgeRegistry<?> registry)
{
private RegistryObject(ResourceLocation name, IForgeRegistry<?> registry) {
if (registry == null)
throw new IllegalArgumentException("Invalid registry argument, must not be null");
this.name = name;
this.key = (ResourceKey<T>) ResourceKey.create(registry.getRegistryKey(), name);
this.optionalRegistry = false;
ObjectHolderRegistry.addHandler(pred ->
{
ObjectHolderRegistry.addHandler(pred -> {
if (pred.test(registry.getRegistryName()))
this.updateReference((IForgeRegistry<? extends T>) registry);
});
this.updateReference((IForgeRegistry<? extends T>) registry);
}
private RegistryObject(final ResourceLocation name, final ResourceLocation registryName, final String modid, boolean optionalRegistry)
{
private RegistryObject(final ResourceLocation name, final ResourceLocation registryName, final String modid, boolean optionalRegistry) {
this.name = name;
this.key = ResourceKey.create(ResourceKey.createRegistryKey(registryName), name);
this.optionalRegistry = optionalRegistry;
final Throwable callerStack = new Throwable("Calling Site from mod: " + modid);
ObjectHolderRegistry.addHandler(new Consumer<>()
{
ObjectHolderRegistry.addHandler(new Consumer<>() {
private boolean registryExists = false;
private boolean invalidRegistry = false;
@Override
public void accept(Predicate<ResourceLocation> pred)
{
public void accept(Predicate<ResourceLocation> pred) {
if (invalidRegistry)
return;
if (!RegistryObject.this.optionalRegistry && !registryExists)
{
if (!registryExists(registryName))
{
if (!RegistryObject.this.optionalRegistry && !registryExists) {
if (!registryExists(registryName)) {
invalidRegistry = true;
registryExists(registryName);
throw new IllegalStateException("Unable to find registry with key " + registryName + " for mod \"" + modid + "\". Check the 'caused by' to see further stack.", callerStack);
}
registryExists = true;
}
if (pred.test(registryName))
RegistryObject.this.updateReference(registryName);
}
@@ -199,62 +187,61 @@ public final class RegistryObject<T> implements Supplier<T>
*/
@NotNull
@Override
public T get()
{
public T get() {
T ret = this.value;
Objects.requireNonNull(ret, () -> "Registry Object not present: " + this.name);
return ret;
}
@SuppressWarnings("unchecked")
void updateReference(IForgeRegistry<? extends T> registry)
{
void updateReference(IForgeRegistry<? extends T> registry) {
if (this.name == null || this.key == null)
return;
if (registry.containsKey(this.name))
{
var wrapper = registry instanceof ForgeRegistry forge ? forge.getWrapper() : null;
if (registry.containsKey(this.name)) {
this.value = registry.getValue(this.name);
this.holder = (Holder<T>) registry.getHolder(this.name).orElse(null);
}
else
{
this.holder = () -> (Holder<T>)registry.getHolder(this.name).orElse(null);
} else if (wrapper != null && !wrapper.isIntrusive()) {
this.value = null;
this.holder = () -> wrapper.createRegistrationLookup().getOrThrow(this.key);
} else {
this.value = null;
this.holder = null;
}
}
@SuppressWarnings("unchecked")
void updateReference(Registry<? extends T> registry)
{
void updateReference(Registry<? extends T> registry) {
if (this.name == null || this.key == null)
return;
if (registry.containsKey(this.name))
{
var mapped = registry instanceof MappedRegistry m ? m : null;
if (registry.containsKey(this.name)) {
this.value = registry.get(this.name);
this.holder = ((Registry<T>) registry).getHolder(this.key).orElse(null);
}
else
{
this.holder = () -> ((Registry<T>)registry).getHolder(this.key).orElse(null);
} else if (mapped != null && !mapped.isIntrusive()) {
this.value = null;
this.holder = () -> mapped.createRegistrationLookup().getOrThrow(this.key);
} else {
this.value = null;
this.holder = null;
}
}
@SuppressWarnings("unchecked")
void updateReference(ResourceLocation registryName)
{
void updateReference(ResourceLocation registryName) {
if (this.name == null)
return;
IForgeRegistry<? extends T> forgeRegistry = RegistryManager.ACTIVE.getRegistry(registryName);
if (forgeRegistry != null)
{
if (forgeRegistry != null) {
updateReference(forgeRegistry);
return;
}
Registry<? extends T> vanillaRegistry = (Registry<? extends T>) BuiltInRegistries.REGISTRY.get(registryName);
if (vanillaRegistry != null)
{
if (vanillaRegistry != null) {
updateReference(vanillaRegistry);
return;
}
@@ -263,11 +250,9 @@ public final class RegistryObject<T> implements Supplier<T>
this.holder = null;
}
void updateReference(RegisterEvent event)
{
void updateReference(RegisterEvent event) {
IForgeRegistry<? extends T> forgeRegistry = event.getForgeRegistry();
if (forgeRegistry != null)
{
if (forgeRegistry != null) {
updateReference(forgeRegistry);
return;
}
@@ -279,14 +264,12 @@ public final class RegistryObject<T> implements Supplier<T>
this.value = null;
}
private static boolean registryExists(ResourceLocation registryName)
{
private static boolean registryExists(ResourceLocation registryName) {
return RegistryManager.ACTIVE.getRegistry(registryName) != null
|| BuiltInRegistries.REGISTRY.containsKey(registryName);
}
public ResourceLocation getId()
{
public ResourceLocation getId() {
return this.name;
}
@@ -297,8 +280,7 @@ public final class RegistryObject<T> implements Supplier<T>
* @return the resource key that points to the registry and name of this registry object
*/
@Nullable
public ResourceKey<T> getKey()
{
public ResourceKey<T> getKey() {
return this.key;
}
@@ -477,24 +459,21 @@ public final class RegistryObject<T> implements Supplier<T>
* @return an optional {@link Holder} instance pointing to this RegistryObject's name and value
*/
@NotNull
public Optional<Holder<T>> getHolder()
{
return Optional.ofNullable(this.holder);
public Optional<Holder<T>> getHolder() {
return Optional.ofNullable(this.holder == null ? null : this.holder.get());
}
@Override
public boolean equals(Object obj)
{
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj instanceof RegistryObject) {
return Objects.equals(((RegistryObject<?>)obj).name, name);
if (obj instanceof RegistryObject o) {
return Objects.equals(o.name, name);
}
return false;
}
@Override
public int hashCode()
{
public int hashCode() {
return Objects.hashCode(name);
}
}