diff --git a/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java b/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java index d0a50ce1..107c931e 100644 --- a/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java +++ b/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java @@ -63,6 +63,7 @@ public class ModernFixEarlyConfig { this.addMixinRule("bugfix.chunk_deadlock", true); this.addMixinRule("perf.thread_priorities", true); this.addMixinRule("perf.scan_cache", true); + this.addMixinRule("perf.kubejs", modPresent("kubejs")); this.addMixinRule("perf.flatten_model_predicates", true); this.addMixinRule("perf.deduplicate_location", false); this.addMixinRule("perf.cache_blockstate_cache_arrays", true); diff --git a/src/main/java/org/embeddedt/modernfix/mixin/perf/kubejs/RecipeEventJSMixin.java b/src/main/java/org/embeddedt/modernfix/mixin/perf/kubejs/RecipeEventJSMixin.java new file mode 100644 index 00000000..964a3129 --- /dev/null +++ b/src/main/java/org/embeddedt/modernfix/mixin/perf/kubejs/RecipeEventJSMixin.java @@ -0,0 +1,50 @@ +package org.embeddedt.modernfix.mixin.perf.kubejs; + +import dev.latvian.mods.kubejs.recipe.RecipeEventJS; +import org.embeddedt.modernfix.ModernFix; +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; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.Collection; +import java.util.Map; + +@Mixin(RecipeEventJS.class) +public class RecipeEventJSMixin { + + /** + * The recipe event object can be leaked in scripts and this wastes 40MB of memory. + */ + @Inject(method = "post", at = @At("RETURN")) + private void clearRecipeLists(CallbackInfo ci) { + ModernFix.LOGGER.info("Clearing KubeJS recipe lists..."); + // Even though we are a mixin class, use reflection so this works across a variety of versions + Field[] fields = RecipeEventJS.class.getDeclaredFields(); + for(Field f : fields) { + try { + if(!Modifier.isStatic(f.getModifiers()) + && (Collection.class.isAssignableFrom(f.getType()) + || Map.class.isAssignableFrom(f.getType())) + ) { + f.setAccessible(true); + Object collection = f.get(this); + int size; + if(collection instanceof Map) { + size = ((Map)collection).size(); + ((Map)collection).clear(); + } else if(collection instanceof Collection) { + size = ((Collection)collection).size(); + ((Collection)collection).clear(); + } else + throw new IllegalStateException(); + ModernFix.LOGGER.debug("Cleared {} with {} entries", f.getName(), size); + } + } catch(RuntimeException | ReflectiveOperationException e) { + ModernFix.LOGGER.debug("Uh oh, couldn't clear field", e); + } + } + } +} diff --git a/src/main/resources/modernfix.mixins.json b/src/main/resources/modernfix.mixins.json index 138c281e..49dd8fcf 100644 --- a/src/main/resources/modernfix.mixins.json +++ b/src/main/resources/modernfix.mixins.json @@ -30,6 +30,7 @@ "feature.branding.BrandingControlMixin", "feature.direct_stack_trace.CrashReportMixin", "perf.fast_registry_validation.ForgeRegistryMixin", + "perf.kubejs.RecipeEventJSMixin", "perf.cache_strongholds.ChunkGeneratorMixin", "perf.cache_upgraded_structures.StructureManagerMixin", "perf.cache_strongholds.ServerLevelMixin",