From 6a25490d7fd753c15d7d0cedc79b6192f650417b Mon Sep 17 00:00:00 2001 From: cpw Date: Sun, 26 Apr 2020 21:03:43 -0400 Subject: [PATCH] Handle message display a bit better, try to make the UI tick a bit better.. Still a problem with a modelbake right at the end, happening on the window flip. Signed-off-by: cpw --- .../minecraftforge/fml/loading/FMLLoader.java | 3 ++- .../moddiscovery/BackgroundScanHandler.java | 27 +++++++++---------- .../minecraftforge/fml/DeferredWorkQueue.java | 6 +++-- .../java/net/minecraftforge/fml/ModList.java | 9 ++++--- .../net/minecraftforge/fml/ModLoader.java | 24 ++++++++++++++--- .../minecraftforge/registries/GameData.java | 4 +++ 6 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/fmllauncher/java/net/minecraftforge/fml/loading/FMLLoader.java b/src/fmllauncher/java/net/minecraftforge/fml/loading/FMLLoader.java index 6aa35eee2..8b6868c79 100644 --- a/src/fmllauncher/java/net/minecraftforge/fml/loading/FMLLoader.java +++ b/src/fmllauncher/java/net/minecraftforge/fml/loading/FMLLoader.java @@ -83,6 +83,7 @@ public class FMLLoader private static String launchHandlerName; private static FMLCommonLaunchHandler commonLaunchHandler; public static Runnable progressWindowTick; + public static BackgroundScanHandler backgroundScanHandler; static void onInitialLoad(IEnvironment environment, Set otherServices) throws IncompatibleEnvironmentException { @@ -207,7 +208,7 @@ public class FMLLoader { LOGGER.debug(SCAN,"Scanning for Mod Locators"); modDiscoverer = new ModDiscoverer(arguments); - final BackgroundScanHandler backgroundScanHandler = modDiscoverer.discoverMods(); + backgroundScanHandler = modDiscoverer.discoverMods(); loadingModList = backgroundScanHandler.getLoadingModList(); commonLaunchHandler.addLibraries(backgroundScanHandler.getModFiles().getOrDefault(IModFile.Type.LIBRARY, Collections.emptyList())); progressWindowTick.run(); diff --git a/src/fmllauncher/java/net/minecraftforge/fml/loading/moddiscovery/BackgroundScanHandler.java b/src/fmllauncher/java/net/minecraftforge/fml/loading/moddiscovery/BackgroundScanHandler.java index 037fec934..7d2afc801 100644 --- a/src/fmllauncher/java/net/minecraftforge/fml/loading/moddiscovery/BackgroundScanHandler.java +++ b/src/fmllauncher/java/net/minecraftforge/fml/loading/moddiscovery/BackgroundScanHandler.java @@ -81,21 +81,6 @@ public class BackgroundScanHandler scannedFiles.add(file); } - public List getScannedFiles() { - if (!pendingFiles.isEmpty()) { - modContentScanner.shutdown(); - try { - modContentScanner.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS); - } catch (InterruptedException e) { - } - } - return scannedFiles; - } - - public List getAllFiles() { - return allFiles; - } - public void setLoadingModList(LoadingModList loadingModList) { this.loadingModList = loadingModList; @@ -105,4 +90,16 @@ public class BackgroundScanHandler { return loadingModList; } + + public void waitForScanToComplete(final Runnable ticker) { + modContentScanner.shutdown(); + do { + ticker.run(); + try { + modContentScanner.awaitTermination(50, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + Thread.interrupted(); + } + } while (!modContentScanner.isShutdown()); + } } diff --git a/src/main/java/net/minecraftforge/fml/DeferredWorkQueue.java b/src/main/java/net/minecraftforge/fml/DeferredWorkQueue.java index 1ef7d0942..24357cabc 100644 --- a/src/main/java/net/minecraftforge/fml/DeferredWorkQueue.java +++ b/src/main/java/net/minecraftforge/fml/DeferredWorkQueue.java @@ -191,12 +191,14 @@ public class DeferredWorkQueue taskQueue.clear(); } - static void runTasks(ModLoadingStage fromStage, Consumer> errorHandler, final Executor executor) { + static Executor workExecutor = Runnable::run; + + static void runTasks(ModLoadingStage fromStage, Consumer> errorHandler) { raisedExceptions.clear(); if (taskQueue.isEmpty()) return; // Don't log unnecessarily LOGGER.info(LOADING, "Dispatching synchronous work after {}: {} jobs", fromStage, taskQueue.size()); StopWatch globalTimer = StopWatch.createStarted(); - final CompletableFuture tasks = CompletableFuture.allOf(taskQueue.stream().map(ti -> makeRunnable(ti, executor)).toArray(CompletableFuture[]::new)); + final CompletableFuture tasks = CompletableFuture.allOf(taskQueue.stream().map(ti -> makeRunnable(ti, workExecutor)).toArray(CompletableFuture[]::new)); tasks.join(); LOGGER.info(LOADING, "Synchronous work queue completed in {}", globalTimer); errorHandler.accept(raisedExceptions); diff --git a/src/main/java/net/minecraftforge/fml/ModList.java b/src/main/java/net/minecraftforge/fml/ModList.java index 2b27506e0..a27fd45a0 100644 --- a/src/main/java/net/minecraftforge/fml/ModList.java +++ b/src/main/java/net/minecraftforge/fml/ModList.java @@ -93,7 +93,7 @@ public class ModList return INSTANCE; } - static LifecycleEventProvider.EventHandler>, Executor, Runnable> inlineDispatcher = (event, errors, executor, ticker) -> ModList.get().dispatchSynchronousEvent(event, errors, executor); + static LifecycleEventProvider.EventHandler>, Executor, Runnable> inlineDispatcher = (event, errors, executor, ticker) -> ModList.get().dispatchSynchronousEvent(event, errors, executor, ticker); static LifecycleEventProvider.EventHandler>, Executor, Runnable> parallelDispatcher = (event, errors, executor, ticker) -> ModList.get().dispatchParallelEvent(event, errors, executor, ticker); @@ -119,10 +119,11 @@ public class ModList return this.fileById.get(modid); } - private void dispatchSynchronousEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent, final Consumer> errorHandler, final Executor executor) { + private void dispatchSynchronousEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent, final Consumer> errorHandler, final Executor executor, final Runnable ticker) { LOGGER.debug(LOADING, "Dispatching synchronous event {}", lifecycleEvent); + executor.execute(ticker); FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.consumeLifecycleEvent(()->lifecycleEvent)); - this.mods.forEach(m->m.transitionState(lifecycleEvent, errorHandler)); + this.mods.stream().forEach(m->m.transitionState(lifecycleEvent, errorHandler)); FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.consumeLifecycleEvent(()->lifecycleEvent)); } private void dispatchParallelEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent, final Consumer> errorHandler, final Executor executor, final Runnable ticker) { @@ -148,7 +149,7 @@ public class ModList throw new RuntimeException("Forge played \"STOP IT NOW MODS!\" - it was \"NOT VERY EFFECTIVE\""); } } - DeferredWorkQueue.runTasks(lifecycleEvent.fromStage(), errorHandler, executor); + DeferredWorkQueue.runTasks(lifecycleEvent.fromStage(), errorHandler); FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.consumeLifecycleEvent(()->lifecycleEvent)); } diff --git a/src/main/java/net/minecraftforge/fml/ModLoader.java b/src/main/java/net/minecraftforge/fml/ModLoader.java index 838ec49e0..69a2d642f 100644 --- a/src/main/java/net/minecraftforge/fml/ModLoader.java +++ b/src/main/java/net/minecraftforge/fml/ModLoader.java @@ -50,6 +50,7 @@ import org.apache.logging.log4j.Logger; import java.nio.file.Path; import java.util.*; import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; @@ -147,6 +148,7 @@ public class ModLoader } public void loadMods(Executor mainThreadExecutor, Consumer>> preSidedRunnable, Consumer>> postSidedRunnable) { + DeferredWorkQueue.workExecutor = mainThreadExecutor; statusConsumer.ifPresent(c->c.accept("Loading mod config")); DistExecutor.runWhenOn(Dist.CLIENT, ()->()-> ConfigTracker.INSTANCE.loadConfigs(ModConfig.Type.CLIENT, FMLPaths.CONFIGDIR.get())); ConfigTracker.INSTANCE.loadConfigs(ModConfig.Type.COMMON, FMLPaths.CONFIGDIR.get()); @@ -159,7 +161,21 @@ public class ModLoader statusConsumer.ifPresent(c->c.accept("Mod setup complete")); } + private static class SpacedRunnable implements Executor { + private static final long FIFTYMILLIS = TimeUnit.MILLISECONDS.toNanos(50); + private long next = System.nanoTime() + FIFTYMILLIS; + @Override + public void execute(final Runnable command) { + final long time = System.nanoTime(); + if (next < time) { + command.run(); + next = time + FIFTYMILLIS; + } + } + } public void gatherAndInitializeMods(final Runnable ticker) { + statusConsumer.ifPresent(c->c.accept("Waiting for scan to complete")); + FMLLoader.backgroundScanHandler.waitForScanToComplete(ticker); statusConsumer.ifPresent(c->c.accept("Loading mods")); final ModList modList = ModList.of(loadingModList.getModFiles().stream().map(ModFileInfo::getFile).collect(Collectors.toList()), loadingModList.getMods()); if (!this.loadingExceptions.isEmpty()) { @@ -179,14 +195,15 @@ public class ModLoader throw new LoadingFailedException(loadingExceptions); } modList.setLoadedMods(modContainers); + SpacedRunnable sr = new SpacedRunnable(); statusConsumer.ifPresent(c->c.accept(String.format("Constructing %d mods", modList.size()))); - dispatchAndHandleError(LifecycleEventProvider.CONSTRUCT, Runnable::run, ticker); + dispatchAndHandleError(LifecycleEventProvider.CONSTRUCT, sr, ticker); statusConsumer.ifPresent(c->c.accept("Creating registries")); - GameData.fireCreateRegistryEvents(LifecycleEventProvider.CREATE_REGISTRIES, event -> dispatchAndHandleError(event, Runnable::run, ticker)); + GameData.fireCreateRegistryEvents(LifecycleEventProvider.CREATE_REGISTRIES, event -> dispatchAndHandleError(event, sr, ticker)); ObjectHolderRegistry.findObjectHolders(); CapabilityManager.INSTANCE.injectCapabilities(modList.getAllScanData()); statusConsumer.ifPresent(c->c.accept("Populating registries")); - GameData.fireRegistryEvents(rl->true, LifecycleEventProvider.LOAD_REGISTRIES, event -> dispatchAndHandleError(event, Runnable::run, ticker)); + GameData.fireRegistryEvents(rl->true, LifecycleEventProvider.LOAD_REGISTRIES, event -> dispatchAndHandleError(event, sr, ticker)); statusConsumer.ifPresent(c->c.accept("Early mod loading complete")); } @@ -245,6 +262,7 @@ public class ModLoader public void finishMods(Executor mainThreadExecutor) { + DeferredWorkQueue.workExecutor = mainThreadExecutor; statusConsumer.ifPresent(c->c.accept("Mod setup: ENQUEUE IMC")); dispatchAndHandleError(LifecycleEventProvider.ENQUEUE_IMC, mainThreadExecutor, null); statusConsumer.ifPresent(c->c.accept("Mod setup: PROCESS IMC")); diff --git a/src/main/java/net/minecraftforge/registries/GameData.java b/src/main/java/net/minecraftforge/registries/GameData.java index 9f3c525c7..deb3c7f35 100644 --- a/src/main/java/net/minecraftforge/registries/GameData.java +++ b/src/main/java/net/minecraftforge/registries/GameData.java @@ -74,6 +74,7 @@ import net.minecraftforge.fml.common.thread.EffectiveSide; import net.minecraftforge.fml.event.lifecycle.FMLModIdMappingEvent; import net.minecraftforge.fml.loading.AdvancedLogMessageAdapter; +import net.minecraftforge.fml.loading.progress.StartupMessageManager; import org.apache.commons.lang3.Validate; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -896,7 +897,9 @@ public class GameData } private static void fireRemapEvent(final Map> remaps, final boolean isFreezing) { + StartupMessageManager.modLoaderConsumer().ifPresent(s->s.accept("Remapping mod data")); MinecraftForge.EVENT_BUS.post(new FMLModIdMappingEvent(remaps, isFreezing)); + StartupMessageManager.modLoaderConsumer().ifPresent(s->s.accept("Remap complete")); } //Has to be split because of generics, Yay! @@ -960,6 +963,7 @@ public class GameData if (!filter.test(rl)) continue; ForgeRegistry reg = RegistryManager.ACTIVE.getRegistry(rl); reg.unfreeze(); + StartupMessageManager.modLoaderConsumer().ifPresent(s->s.accept("REGISTERING "+rl)); final RegistryEvent.Register registerEvent = reg.getRegisterEvent(rl); lifecycleEventProvider.setCustomEventSupplier(() -> registerEvent); lifecycleEventProvider.changeProgression(LifecycleEventProvider.LifecycleEvent.Progression.STAY);