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();
|
ObjectHolderClearer.clearThrowables();
|
||||||
|
event.enqueueWork(ObjectHolderClearer::removeRedundantHolders);
|
||||||
}
|
}
|
||||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||||
public void onServerDead(ServerStoppedEvent event) {
|
public void onServerDead(ServerStoppedEvent event) {
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,14 @@ package org.embeddedt.modernfix.forge.registry;
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||||
|
import net.minecraftforge.registries.ForgeRegistry;
|
||||||
import net.minecraftforge.registries.ObjectHolderRegistry;
|
import net.minecraftforge.registries.ObjectHolderRegistry;
|
||||||
import org.embeddedt.modernfix.ModernFix;
|
import org.embeddedt.modernfix.ModernFix;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
@ -43,4 +46,47 @@ public class ObjectHolderClearer {
|
||||||
ModernFix.LOGGER.debug("Cleared " + numCleared + " object holder stacktrace references");
|
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