Clear unneeded ObjectHolderRefs
This commit is contained in:
parent
21cbcb0e04
commit
f23348c6cb
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -125,6 +125,7 @@ public class ModernFixForge {
|
|||
});
|
||||
}
|
||||
ObjectHolderClearer.clearThrowables();
|
||||
event.enqueueWork(ObjectHolderClearer::removeRedundantHolders);
|
||||
}
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
public void onServerDead(ServerStoppedEvent event) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user