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 <cpw+github@weeksfamily.ca>
This commit is contained in:
cpw 2020-04-26 21:03:43 -04:00
parent 6a0b16817d
commit 6a25490d7f
No known key found for this signature in database
GPG key ID: 8EB3DF749553B1B7
6 changed files with 48 additions and 25 deletions

View file

@ -83,6 +83,7 @@ public class FMLLoader
private static String launchHandlerName; private static String launchHandlerName;
private static FMLCommonLaunchHandler commonLaunchHandler; private static FMLCommonLaunchHandler commonLaunchHandler;
public static Runnable progressWindowTick; public static Runnable progressWindowTick;
public static BackgroundScanHandler backgroundScanHandler;
static void onInitialLoad(IEnvironment environment, Set<String> otherServices) throws IncompatibleEnvironmentException static void onInitialLoad(IEnvironment environment, Set<String> otherServices) throws IncompatibleEnvironmentException
{ {
@ -207,7 +208,7 @@ public class FMLLoader
{ {
LOGGER.debug(SCAN,"Scanning for Mod Locators"); LOGGER.debug(SCAN,"Scanning for Mod Locators");
modDiscoverer = new ModDiscoverer(arguments); modDiscoverer = new ModDiscoverer(arguments);
final BackgroundScanHandler backgroundScanHandler = modDiscoverer.discoverMods(); backgroundScanHandler = modDiscoverer.discoverMods();
loadingModList = backgroundScanHandler.getLoadingModList(); loadingModList = backgroundScanHandler.getLoadingModList();
commonLaunchHandler.addLibraries(backgroundScanHandler.getModFiles().getOrDefault(IModFile.Type.LIBRARY, Collections.emptyList())); commonLaunchHandler.addLibraries(backgroundScanHandler.getModFiles().getOrDefault(IModFile.Type.LIBRARY, Collections.emptyList()));
progressWindowTick.run(); progressWindowTick.run();

View file

@ -81,21 +81,6 @@ public class BackgroundScanHandler
scannedFiles.add(file); scannedFiles.add(file);
} }
public List<ModFile> getScannedFiles() {
if (!pendingFiles.isEmpty()) {
modContentScanner.shutdown();
try {
modContentScanner.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
} catch (InterruptedException e) {
}
}
return scannedFiles;
}
public List<ModFile> getAllFiles() {
return allFiles;
}
public void setLoadingModList(LoadingModList loadingModList) public void setLoadingModList(LoadingModList loadingModList)
{ {
this.loadingModList = loadingModList; this.loadingModList = loadingModList;
@ -105,4 +90,16 @@ public class BackgroundScanHandler
{ {
return loadingModList; 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());
}
} }

View file

@ -191,12 +191,14 @@ public class DeferredWorkQueue
taskQueue.clear(); taskQueue.clear();
} }
static void runTasks(ModLoadingStage fromStage, Consumer<List<ModLoadingException>> errorHandler, final Executor executor) { static Executor workExecutor = Runnable::run;
static void runTasks(ModLoadingStage fromStage, Consumer<List<ModLoadingException>> errorHandler) {
raisedExceptions.clear(); raisedExceptions.clear();
if (taskQueue.isEmpty()) return; // Don't log unnecessarily if (taskQueue.isEmpty()) return; // Don't log unnecessarily
LOGGER.info(LOADING, "Dispatching synchronous work after {}: {} jobs", fromStage, taskQueue.size()); LOGGER.info(LOADING, "Dispatching synchronous work after {}: {} jobs", fromStage, taskQueue.size());
StopWatch globalTimer = StopWatch.createStarted(); StopWatch globalTimer = StopWatch.createStarted();
final CompletableFuture<Void> tasks = CompletableFuture.allOf(taskQueue.stream().map(ti -> makeRunnable(ti, executor)).toArray(CompletableFuture[]::new)); final CompletableFuture<Void> tasks = CompletableFuture.allOf(taskQueue.stream().map(ti -> makeRunnable(ti, workExecutor)).toArray(CompletableFuture[]::new));
tasks.join(); tasks.join();
LOGGER.info(LOADING, "Synchronous work queue completed in {}", globalTimer); LOGGER.info(LOADING, "Synchronous work queue completed in {}", globalTimer);
errorHandler.accept(raisedExceptions); errorHandler.accept(raisedExceptions);

View file

@ -93,7 +93,7 @@ public class ModList
return INSTANCE; return INSTANCE;
} }
static LifecycleEventProvider.EventHandler<LifecycleEventProvider.LifecycleEvent, Consumer<List<ModLoadingException>>, Executor, Runnable> inlineDispatcher = (event, errors, executor, ticker) -> ModList.get().dispatchSynchronousEvent(event, errors, executor); static LifecycleEventProvider.EventHandler<LifecycleEventProvider.LifecycleEvent, Consumer<List<ModLoadingException>>, Executor, Runnable> inlineDispatcher = (event, errors, executor, ticker) -> ModList.get().dispatchSynchronousEvent(event, errors, executor, ticker);
static LifecycleEventProvider.EventHandler<LifecycleEventProvider.LifecycleEvent, Consumer<List<ModLoadingException>>, Executor, Runnable> parallelDispatcher = (event, errors, executor, ticker) -> ModList.get().dispatchParallelEvent(event, errors, executor, ticker); static LifecycleEventProvider.EventHandler<LifecycleEventProvider.LifecycleEvent, Consumer<List<ModLoadingException>>, 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); return this.fileById.get(modid);
} }
private void dispatchSynchronousEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent, final Consumer<List<ModLoadingException>> errorHandler, final Executor executor) { private void dispatchSynchronousEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent, final Consumer<List<ModLoadingException>> errorHandler, final Executor executor, final Runnable ticker) {
LOGGER.debug(LOADING, "Dispatching synchronous event {}", lifecycleEvent); LOGGER.debug(LOADING, "Dispatching synchronous event {}", lifecycleEvent);
executor.execute(ticker);
FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.consumeLifecycleEvent(()->lifecycleEvent)); 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)); FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.consumeLifecycleEvent(()->lifecycleEvent));
} }
private void dispatchParallelEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent, final Consumer<List<ModLoadingException>> errorHandler, final Executor executor, final Runnable ticker) { private void dispatchParallelEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent, final Consumer<List<ModLoadingException>> 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\""); 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)); FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.consumeLifecycleEvent(()->lifecycleEvent));
} }

View file

@ -50,6 +50,7 @@ import org.apache.logging.log4j.Logger;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.*; import java.util.*;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -147,6 +148,7 @@ public class ModLoader
} }
public void loadMods(Executor mainThreadExecutor, Consumer<Consumer<Supplier<Event>>> preSidedRunnable, Consumer<Consumer<Supplier<Event>>> postSidedRunnable) { public void loadMods(Executor mainThreadExecutor, Consumer<Consumer<Supplier<Event>>> preSidedRunnable, Consumer<Consumer<Supplier<Event>>> postSidedRunnable) {
DeferredWorkQueue.workExecutor = mainThreadExecutor;
statusConsumer.ifPresent(c->c.accept("Loading mod config")); statusConsumer.ifPresent(c->c.accept("Loading mod config"));
DistExecutor.runWhenOn(Dist.CLIENT, ()->()-> ConfigTracker.INSTANCE.loadConfigs(ModConfig.Type.CLIENT, FMLPaths.CONFIGDIR.get())); DistExecutor.runWhenOn(Dist.CLIENT, ()->()-> ConfigTracker.INSTANCE.loadConfigs(ModConfig.Type.CLIENT, FMLPaths.CONFIGDIR.get()));
ConfigTracker.INSTANCE.loadConfigs(ModConfig.Type.COMMON, 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")); 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) { 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")); statusConsumer.ifPresent(c->c.accept("Loading mods"));
final ModList modList = ModList.of(loadingModList.getModFiles().stream().map(ModFileInfo::getFile).collect(Collectors.toList()), loadingModList.getMods()); final ModList modList = ModList.of(loadingModList.getModFiles().stream().map(ModFileInfo::getFile).collect(Collectors.toList()), loadingModList.getMods());
if (!this.loadingExceptions.isEmpty()) { if (!this.loadingExceptions.isEmpty()) {
@ -179,14 +195,15 @@ public class ModLoader
throw new LoadingFailedException(loadingExceptions); throw new LoadingFailedException(loadingExceptions);
} }
modList.setLoadedMods(modContainers); modList.setLoadedMods(modContainers);
SpacedRunnable sr = new SpacedRunnable();
statusConsumer.ifPresent(c->c.accept(String.format("Constructing %d mods", modList.size()))); 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")); 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(); ObjectHolderRegistry.findObjectHolders();
CapabilityManager.INSTANCE.injectCapabilities(modList.getAllScanData()); CapabilityManager.INSTANCE.injectCapabilities(modList.getAllScanData());
statusConsumer.ifPresent(c->c.accept("Populating registries")); 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")); statusConsumer.ifPresent(c->c.accept("Early mod loading complete"));
} }
@ -245,6 +262,7 @@ public class ModLoader
public void finishMods(Executor mainThreadExecutor) public void finishMods(Executor mainThreadExecutor)
{ {
DeferredWorkQueue.workExecutor = mainThreadExecutor;
statusConsumer.ifPresent(c->c.accept("Mod setup: ENQUEUE IMC")); statusConsumer.ifPresent(c->c.accept("Mod setup: ENQUEUE IMC"));
dispatchAndHandleError(LifecycleEventProvider.ENQUEUE_IMC, mainThreadExecutor, null); dispatchAndHandleError(LifecycleEventProvider.ENQUEUE_IMC, mainThreadExecutor, null);
statusConsumer.ifPresent(c->c.accept("Mod setup: PROCESS IMC")); statusConsumer.ifPresent(c->c.accept("Mod setup: PROCESS IMC"));

View file

@ -74,6 +74,7 @@ import net.minecraftforge.fml.common.thread.EffectiveSide;
import net.minecraftforge.fml.event.lifecycle.FMLModIdMappingEvent; import net.minecraftforge.fml.event.lifecycle.FMLModIdMappingEvent;
import net.minecraftforge.fml.loading.AdvancedLogMessageAdapter; import net.minecraftforge.fml.loading.AdvancedLogMessageAdapter;
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -896,7 +897,9 @@ public class GameData
} }
private static void fireRemapEvent(final Map<ResourceLocation, Map<ResourceLocation, Integer[]>> remaps, final boolean isFreezing) { private static void fireRemapEvent(final Map<ResourceLocation, Map<ResourceLocation, Integer[]>> remaps, final boolean isFreezing) {
StartupMessageManager.modLoaderConsumer().ifPresent(s->s.accept("Remapping mod data"));
MinecraftForge.EVENT_BUS.post(new FMLModIdMappingEvent(remaps, isFreezing)); MinecraftForge.EVENT_BUS.post(new FMLModIdMappingEvent(remaps, isFreezing));
StartupMessageManager.modLoaderConsumer().ifPresent(s->s.accept("Remap complete"));
} }
//Has to be split because of generics, Yay! //Has to be split because of generics, Yay!
@ -960,6 +963,7 @@ public class GameData
if (!filter.test(rl)) continue; if (!filter.test(rl)) continue;
ForgeRegistry<?> reg = RegistryManager.ACTIVE.getRegistry(rl); ForgeRegistry<?> reg = RegistryManager.ACTIVE.getRegistry(rl);
reg.unfreeze(); reg.unfreeze();
StartupMessageManager.modLoaderConsumer().ifPresent(s->s.accept("REGISTERING "+rl));
final RegistryEvent.Register<?> registerEvent = reg.getRegisterEvent(rl); final RegistryEvent.Register<?> registerEvent = reg.getRegisterEvent(rl);
lifecycleEventProvider.setCustomEventSupplier(() -> registerEvent); lifecycleEventProvider.setCustomEventSupplier(() -> registerEvent);
lifecycleEventProvider.changeProgression(LifecycleEventProvider.LifecycleEvent.Progression.STAY); lifecycleEventProvider.changeProgression(LifecycleEventProvider.LifecycleEvent.Progression.STAY);