Clear KubeJS recipe event lists since mods can hold onto the event object

This commit is contained in:
embeddedt 2023-04-25 19:29:26 -04:00
parent 7c793c7fb6
commit e843f8ed6d
No known key found for this signature in database
GPG Key ID: A69433EC199B5613

View File

@ -7,6 +7,7 @@ import dev.latvian.kubejs.recipe.RecipeJS;
import dev.latvian.kubejs.recipe.filter.RecipeFilter;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.RecipeManager;
import org.embeddedt.modernfix.ModernFix;
import org.embeddedt.modernfix.util.KubeUtil;
import org.embeddedt.modernfix.util.ModUtil;
import org.spongepowered.asm.mixin.Final;
@ -17,6 +18,9 @@ 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.List;
import java.util.Map;
import java.util.function.Consumer;
@ -51,4 +55,37 @@ public class RecipeEventJSMixin {
private void clearRecipeRegistry(RecipeManager manager, Map<ResourceLocation, JsonObject> jsonMap, CallbackInfo ci) {
KubeUtil.originalRecipesByHash.clear();
}
/**
* 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);
}
}
}
}