Clear unneeded ObjectHolderRefs

This commit is contained in:
embeddedt 2026-03-01 19:28:52 -05:00
parent 21cbcb0e04
commit f23348c6cb
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
3 changed files with 63 additions and 0 deletions

View File

@ -0,0 +1,16 @@
package org.embeddedt.modernfix.common.mixin.perf.object_holder_cleanup;
import net.minecraftforge.registries.GameData;
import org.embeddedt.modernfix.forge.registry.ObjectHolderClearer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(value = GameData.class, remap = false)
public class GameDataMixin {
@Inject(method = "postRegisterEvents", at = @At("RETURN"))
private static void clearRedundantHolders(CallbackInfo ci) {
ObjectHolderClearer.removeRedundantHolders();
}
}

View File

@ -125,6 +125,7 @@ public class ModernFixForge {
});
}
ObjectHolderClearer.clearThrowables();
event.enqueueWork(ObjectHolderClearer::removeRedundantHolders);
}
@SubscribeEvent(priority = EventPriority.LOWEST)
public void onServerDead(ServerStoppedEvent event) {

View File

@ -2,11 +2,14 @@ package org.embeddedt.modernfix.forge.registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
import net.minecraftforge.registries.ForgeRegistry;
import net.minecraftforge.registries.ObjectHolderRegistry;
import org.embeddedt.modernfix.ModernFix;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
@ -43,4 +46,47 @@ public class ObjectHolderClearer {
ModernFix.LOGGER.debug("Cleared " + numCleared + " object holder stacktrace references");
}
}
public static void removeRedundantHolders() {
try {
Field holdersField = ObjectHolderRegistry.class.getDeclaredField("objectHolders");
holdersField.setAccessible(true);
Set<Consumer<Predicate<ResourceLocation>>> holders = (Set<Consumer<Predicate<ResourceLocation>>>)holdersField.get(null);
Class<?> refClass = Class.forName("net.minecraftforge.registries.ObjectHolderRef");
Field registryField = refClass.getDeclaredField("registry");
registryField.setAccessible(true);
Field injectedObjectField = refClass.getDeclaredField("injectedObject");
injectedObjectField.setAccessible(true);
Method getOverrideOwnersMethod = ForgeRegistry.class.getDeclaredMethod("getOverrideOwners");
getOverrideOwnersMethod.setAccessible(true);
HashMap<ForgeRegistry<?>, Map<ResourceLocation, String>> overrideCache = new HashMap<>();
int removed = 0;
var it = holders.iterator();
while (it.hasNext()) {
var holder = it.next();
if (!refClass.isInstance(holder))
continue;
ForgeRegistry<?> registry = (ForgeRegistry<?>)registryField.get(holder);
ResourceLocation injectedObject = (ResourceLocation)injectedObjectField.get(holder);
Map<ResourceLocation, String> overrides = overrideCache.computeIfAbsent(registry, r -> {
try {
return (Map<ResourceLocation, String>)getOverrideOwnersMethod.invoke(r);
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
});
if (!overrides.containsKey(injectedObject)) {
it.remove();
removed++;
}
}
ModernFix.LOGGER.debug("Removed {} redundant object holders", removed);
} catch (Exception e) {
ModernFix.LOGGER.error("Failed to remove object holders", e);
}
}
}