package org.embeddedt.modernfix; import net.minecraft.client.Minecraft; import net.minecraft.server.MinecraftServer; import net.minecraft.util.MemoryReserve; import org.embeddedt.modernfix.api.constants.IntegrationConstants; import org.embeddedt.modernfix.api.entrypoint.ModernFixClientIntegration; import org.embeddedt.modernfix.core.ModernFixMixinPlugin; import org.embeddedt.modernfix.platform.ModernFixPlatformHooks; import org.embeddedt.modernfix.searchtree.JEIBackedSearchTree; import org.embeddedt.modernfix.searchtree.SearchTreeProviderRegistry; import org.embeddedt.modernfix.spark.SparkLaunchProfiler; import org.embeddedt.modernfix.util.ClassInfoManager; import org.embeddedt.modernfix.world.IntegratedWatchdog; import java.lang.management.ManagementFactory; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; public class ModernFixClient { public static ModernFixClient INSTANCE; public static long worldLoadStartTime = -1; private static int numRenderTicks; public static float gameStartTimeSeconds = -1; public static boolean recipesUpdated, tagsUpdated = false; public String brandingString = null; /** * The list of loaded client integrations. */ public static List CLIENT_INTEGRATIONS = new CopyOnWriteArrayList<>(); public ModernFixClient() { INSTANCE = this; // clear reserve as it's not needed MemoryReserve.release(); if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.branding.F3Screen")) { brandingString = ModernFix.NAME + " " + ModernFixPlatformHooks.INSTANCE.getVersionString(); } SearchTreeProviderRegistry.register(JEIBackedSearchTree.PROVIDER); for(String className : ModernFixPlatformHooks.INSTANCE.getCustomModOptions().get(IntegrationConstants.CLIENT_INTEGRATION_CLASS)) { try { CLIENT_INTEGRATIONS.add((ModernFixClientIntegration)Class.forName(className).getDeclaredConstructor().newInstance()); } catch(ReflectiveOperationException | ClassCastException e) { ModernFix.LOGGER.error("Could not instantiate integration {}", className, e); } } if(ModernFixMixinPlugin.instance.isOptionEnabled("perf.dynamic_resources.FireIntegrationHook")) { for(ModernFixClientIntegration integration : ModernFixClient.CLIENT_INTEGRATIONS) { integration.onDynamicResourcesStatusChange(true); } } } public void resetWorldLoadStateMachine() { numRenderTicks = 0; worldLoadStartTime = -1; recipesUpdated = false; tagsUpdated = false; } public void onGameLaunchFinish() { if(gameStartTimeSeconds >= 0) return; gameStartTimeSeconds = ManagementFactory.getRuntimeMXBean().getUptime() / 1000f; if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.measure_time.GameLoad")) ModernFix.LOGGER.warn("Game took " + gameStartTimeSeconds + " seconds to start"); ModernFixPlatformHooks.INSTANCE.onLaunchComplete(); ClassInfoManager.clear(); } public void onRecipesUpdated() { recipesUpdated = true; } public void onTagsUpdated() { tagsUpdated = true; } public void onRenderTickEnd() { if(recipesUpdated && tagsUpdated && worldLoadStartTime != -1 && Minecraft.getInstance().player != null && numRenderTicks++ >= 10) { float timeSpentLoading = ((float)(System.nanoTime() - worldLoadStartTime) / 1000000000f); if(ModernFixMixinPlugin.instance.isOptionEnabled("feature.measure_time.WorldLoad")) { ModernFix.LOGGER.warn("Time from main menu to in-game was " + timeSpentLoading + " seconds"); ModernFix.LOGGER.warn("Total time to load game and open world was " + (timeSpentLoading + gameStartTimeSeconds) + " seconds"); } if (ModernFixPlatformHooks.INSTANCE.modPresent("spark") && ModernFixMixinPlugin.instance.isOptionEnabled("feature.spark_profile_world_join.WorldJoin")) { SparkLaunchProfiler.stop("world_join"); } resetWorldLoadStateMachine(); } } public void onServerStarted(MinecraftServer server) { if(!ModernFixMixinPlugin.instance.isOptionEnabled("feature.integrated_server_watchdog.IntegratedWatchdog")) return; IntegratedWatchdog watchdog = new IntegratedWatchdog(server); watchdog.start(); } }