From fc1f2be05bd31d102b3342d6542c46175216736e Mon Sep 17 00:00:00 2001 From: MelanX Date: Sun, 12 Apr 2026 10:07:04 +0200 Subject: [PATCH] Fix orphaned intrusive holders when a RegistryCondition skips an entry When RegistrationDispatcher.register() returned early because a RegistryCondition evaluated to false, the early return skipped the registerAdditional() call but did not clean up any intrusive holder that the entry's constructor may have already allocated via MappedRegistry.createIntrusiveHolder(). The holder was left in MappedRegistry.unregisteredIntrusiveHolders but never bound, so when the registry froze at world load, Minecraft threw "Some intrusive holders were not registered". --- .../registration/RegistrationDispatcher.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/moddingx/libx/impl/registration/RegistrationDispatcher.java b/src/main/java/org/moddingx/libx/impl/registration/RegistrationDispatcher.java index f05570e9..2cf737ca 100644 --- a/src/main/java/org/moddingx/libx/impl/registration/RegistrationDispatcher.java +++ b/src/main/java/org/moddingx/libx/impl/registration/RegistrationDispatcher.java @@ -1,5 +1,7 @@ package org.moddingx.libx.impl.registration; +import net.minecraft.core.MappedRegistry; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; @@ -89,7 +91,12 @@ public void register(@Nullable ResourceKey> registry, RegistrationContext ctx = new RegistrationContext(this.mod, rl, resourceKey); List failedConditions = this.conditions.stream().filter(condition -> !condition.shouldRegister(ctx, value)).toList(); - if (!failedConditions.isEmpty()) return; + if (!failedConditions.isEmpty()) { + if (registry != null) { + cleanupIntrusiveHolder(registry, value); + } + return; + } EntryCollectorImpl collector = new EntryCollectorImpl(this, id); @@ -144,6 +151,14 @@ private void registerClient(FMLClientSetupEvent event) { this.runRegistration(); this.registerables.forEach(reg -> reg.registerClient(event::enqueueWork)); } + + @SuppressWarnings("unchecked") + private static void cleanupIntrusiveHolder(ResourceKey> registryKey, T value) { + Registry registry = (Registry) BuiltInRegistries.REGISTRY.get(registryKey.location()); + if (registry instanceof MappedRegistry mappedRegistry && mappedRegistry.unregisteredIntrusiveHolders != null) { + mappedRegistry.unregisteredIntrusiveHolders.remove(value); + } + } private record NamedRegisterable(RegistrationContext ctx, Registerable value) { @@ -176,7 +191,7 @@ public List, Object>> values() { return Collections.unmodifiableList(this.values); } } - + // Safely reference the client only methods from registerable private static class RegisterableClientAdapter {