From 318afbe3bf4395ade880ff7d9344938559c733fb Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Sun, 12 Feb 2023 10:25:58 -0500 Subject: [PATCH] Automatically detect mods that need models baked in advance --- .../perf/faster_baking/ModelBakeryMixin.java | 11 +++- .../org/embeddedt/modernfix/util/ModUtil.java | 52 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/embeddedt/modernfix/util/ModUtil.java diff --git a/src/main/java/org/embeddedt/modernfix/mixin/perf/faster_baking/ModelBakeryMixin.java b/src/main/java/org/embeddedt/modernfix/mixin/perf/faster_baking/ModelBakeryMixin.java index b004ccb2..8bcbc730 100644 --- a/src/main/java/org/embeddedt/modernfix/mixin/perf/faster_baking/ModelBakeryMixin.java +++ b/src/main/java/org/embeddedt/modernfix/mixin/perf/faster_baking/ModelBakeryMixin.java @@ -14,6 +14,12 @@ import net.minecraft.profiler.IProfiler; import net.minecraft.util.ResourceLocation; import net.minecraft.util.Util; import net.minecraft.util.math.vector.TransformationMatrix; +import net.minecraftforge.client.event.ModelBakeEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.EventBus; +import net.minecraftforge.eventbus.api.EventListenerHelper; +import net.minecraftforge.eventbus.api.IEventListener; +import net.minecraftforge.fml.common.ObfuscationReflectionHelper; import net.minecraftforge.fml.loading.progress.StartupMessageManager; import org.apache.commons.lang3.tuple.Triple; import org.apache.logging.log4j.Logger; @@ -22,6 +28,7 @@ import org.embeddedt.modernfix.ModernFixClient; import org.embeddedt.modernfix.core.config.ModernFixConfig; import org.embeddedt.modernfix.duck.IExtendedModelBakery; import org.embeddedt.modernfix.models.LazyBakedModel; +import org.embeddedt.modernfix.util.ModUtil; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -84,9 +91,11 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { this.atlasSet = new SpriteMap(this.atlasPreparations.values().stream().map(Pair::getFirst).collect(Collectors.toList())); IBakedModel missingModel = this.bake(MISSING_MODEL_LOCATION, ModelRotation.X0_Y0); this.bakedTopLevelModels.put(MISSING_MODEL_LOCATION, missingModel); + Collection modsListening = ModUtil.findAllModsListeningToEvent(ModelBakeEvent.class); + LOGGER.debug("Found ModelBakeEvent listeners: [" + String.join(", ", modsListening) + "]"); Set incompatibleLazyBakedModels = ImmutableSet.builder() .addAll(ModernFixConfig.MODELS_TO_BAKE.get()) - .add("betterfoliage") + .addAll(modsListening) .build(); /* First, bake any incompatible models ahead of time (for mods that have custom models) */ this.unbakedCache.keySet().forEach(location -> { diff --git a/src/main/java/org/embeddedt/modernfix/util/ModUtil.java b/src/main/java/org/embeddedt/modernfix/util/ModUtil.java new file mode 100644 index 00000000..e82d0982 --- /dev/null +++ b/src/main/java/org/embeddedt/modernfix/util/ModUtil.java @@ -0,0 +1,52 @@ +package org.embeddedt.modernfix.util; + +import net.minecraftforge.client.event.ModelBakeEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.EventBus; +import net.minecraftforge.eventbus.api.EventListenerHelper; +import net.minecraftforge.eventbus.api.IEventListener; +import net.minecraftforge.fml.ModContainer; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.ModLoader; +import net.minecraftforge.fml.ModLoadingContext; +import net.minecraftforge.fml.common.ObfuscationReflectionHelper; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import org.embeddedt.modernfix.ModernFix; + +import java.util.*; +import java.util.function.Supplier; + +public class ModUtil { + private static final Set> erroredContexts = new HashSet<>(); + private static boolean busListensToEvent(EventBus bus, Class eventClazz) { + try { + int busID = ObfuscationReflectionHelper.getPrivateValue(EventBus.class, bus, "busID"); + return EventListenerHelper.getListenerList(eventClazz).getListeners(busID).length > 0; + } catch(Exception e) { + ModernFix.LOGGER.error(e); + return false; + } + } + public static Collection findAllModsListeningToEvent(Class eventClazz) { + Set modsListening = new HashSet<>(); + ModList.get().forEachModContainer((modId, container) -> { + Supplier languageExtensionSupplier = ObfuscationReflectionHelper.getPrivateValue(ModContainer.class, container, "contextExtension"); + Object context = languageExtensionSupplier.get(); + if(context == null) + return; + if(context instanceof FMLJavaModLoadingContext) { + if(busListensToEvent((EventBus)((FMLJavaModLoadingContext) context).getModEventBus(), eventClazz)) { + modsListening.add(modId); + } + } else { + synchronized(erroredContexts) { + if(!erroredContexts.contains(context.getClass())) { + ModernFix.LOGGER.warn("Unknown modloading context: " + context.getClass().getName()); + erroredContexts.add(context.getClass()); + } + } + } + }); + return modsListening; + } +}