diff --git a/src/main/java/org/embeddedt/modernfix/ModernFix.java b/src/main/java/org/embeddedt/modernfix/ModernFix.java index 3e4ee13a..5c455d43 100644 --- a/src/main/java/org/embeddedt/modernfix/ModernFix.java +++ b/src/main/java/org/embeddedt/modernfix/ModernFix.java @@ -21,6 +21,10 @@ import org.embeddedt.modernfix.structure.AsyncLocator; import org.embeddedt.modernfix.util.KubeUtil; import java.lang.management.ManagementFactory; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.function.BooleanSupplier; // The value here should match an entry in the META-INF/mods.toml file @Mod(ModernFix.MODID) @@ -36,6 +40,26 @@ public class ModernFix { // Used to skip computing the blockstate caches twice public static boolean runningFirstInjection = false; + public static CountDownLatch worldLoadSemaphore = null; + + /** + * Simple mechanism used to delay some background processes until the client is actually in-game, to reduce + * launch time. + */ + public static void waitForWorldLoad(BooleanSupplier exitEarly) { + CountDownLatch latch = worldLoadSemaphore; + if(latch != null) { + try { + while(!latch.await(100, TimeUnit.MILLISECONDS)) { + if(exitEarly.getAsBoolean()) + return; + } + } catch(InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + public ModernFix() { INSTANCE = this; diff --git a/src/main/java/org/embeddedt/modernfix/ModernFixClient.java b/src/main/java/org/embeddedt/modernfix/ModernFixClient.java index 1ce231d7..2ed3b0c3 100644 --- a/src/main/java/org/embeddedt/modernfix/ModernFixClient.java +++ b/src/main/java/org/embeddedt/modernfix/ModernFixClient.java @@ -48,6 +48,8 @@ public class ModernFixClient { 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"); resetWorldLoadStateMachine(); + if(ModernFix.worldLoadSemaphore != null) + ModernFix.worldLoadSemaphore.countDown(); } } } diff --git a/src/main/java/org/embeddedt/modernfix/blockstate/BlockStateCacheHandler.java b/src/main/java/org/embeddedt/modernfix/blockstate/BlockStateCacheHandler.java index 4128d2d9..e9bd7c9f 100644 --- a/src/main/java/org/embeddedt/modernfix/blockstate/BlockStateCacheHandler.java +++ b/src/main/java/org/embeddedt/modernfix/blockstate/BlockStateCacheHandler.java @@ -85,6 +85,9 @@ public class BlockStateCacheHandler { @Override public void run() { + ModernFix.waitForWorldLoad(() -> stopRebuild); + if(stopRebuild) + return; Stopwatch realtimeStopwatch = Stopwatch.createStarted(); rebuildCache(); realtimeStopwatch.stop(); diff --git a/src/main/java/org/embeddedt/modernfix/mixin/core/MinecraftMixin.java b/src/main/java/org/embeddedt/modernfix/mixin/core/MinecraftMixin.java new file mode 100644 index 00000000..7665941d --- /dev/null +++ b/src/main/java/org/embeddedt/modernfix/mixin/core/MinecraftMixin.java @@ -0,0 +1,25 @@ +package org.embeddedt.modernfix.mixin.core; + +import com.mojang.datafixers.util.Function4; +import net.minecraft.client.Minecraft; +import net.minecraft.core.RegistryAccess; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.world.level.DataPackConfig; +import net.minecraft.world.level.storage.LevelStorageSource; +import net.minecraft.world.level.storage.WorldData; +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.util.concurrent.CountDownLatch; +import java.util.function.Function; + +@Mixin(Minecraft.class) +public class MinecraftMixin { + @Inject(method = "loadWorld", at = @At("HEAD")) + private void setLatch(String string, RegistryAccess.RegistryHolder arg, Function function, Function4 function4, boolean bl, Minecraft.ExperimentalDialogType arg2, boolean creating, CallbackInfo ci) { + ModernFix.worldLoadSemaphore = new CountDownLatch(1); + } +} diff --git a/src/main/java/org/embeddedt/modernfix/mixin/perf/async_jei/ClientLifecycleHandlerMixin.java b/src/main/java/org/embeddedt/modernfix/mixin/perf/async_jei/ClientLifecycleHandlerMixin.java index 6a1d664b..d7708b98 100644 --- a/src/main/java/org/embeddedt/modernfix/mixin/perf/async_jei/ClientLifecycleHandlerMixin.java +++ b/src/main/java/org/embeddedt/modernfix/mixin/perf/async_jei/ClientLifecycleHandlerMixin.java @@ -80,6 +80,9 @@ public class ClientLifecycleHandlerMixin { cancelPreviousStart(); ModernFix.LOGGER.info("Starting new JEI thread."); JEIReloadThread newThread = new JEIReloadThread(() -> { + ModernFix.waitForWorldLoad(() -> ((JEIReloadThread)Thread.currentThread()).isStopRequested()); + if(((JEIReloadThread)Thread.currentThread()).isStopRequested()) + return; try { starter.start( plugins, diff --git a/src/main/resources/modernfix.mixins.json b/src/main/resources/modernfix.mixins.json index f7a43a5a..5dd2746e 100644 --- a/src/main/resources/modernfix.mixins.json +++ b/src/main/resources/modernfix.mixins.json @@ -50,6 +50,7 @@ "perf.kubejs.CustomIngredientMixin" ], "client": [ + "core.MinecraftMixin", "feature.measure_time.MinecraftMixin", "feature.reduce_loading_screen_freezes.ModelBakeryMixin", "perf.skip_first_datapack_reload.MinecraftMixin",