diff --git a/patches/minecraft/net/minecraft/client/gui/ResourceLoadProgressGui.java.patch b/patches/minecraft/net/minecraft/client/gui/ResourceLoadProgressGui.java.patch new file mode 100644 index 0000000000..1c59e480fe --- /dev/null +++ b/patches/minecraft/net/minecraft/client/gui/ResourceLoadProgressGui.java.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/client/gui/ResourceLoadProgressGui.java ++++ b/net/minecraft/client/gui/ResourceLoadProgressGui.java +@@ -83,6 +83,7 @@ + this.func_212972_a(i / 2 - 150, j / 4 * 3, i / 2 + 150, j / 4 * 3 + 10, this.field_212978_f, 1.0F - MathHelper.func_76131_a(f, 0.0F, 1.0F)); + } + ++ net.minecraftforge.fml.client.ClientModLoader.renderProgressText(); + if (f >= 2.0F) { + this.field_212974_b.func_213268_a((LoadingGui)null); + } diff --git a/src/main/java/net/minecraftforge/fml/ModLoader.java b/src/main/java/net/minecraftforge/fml/ModLoader.java index 977af62c21..7dab12a313 100644 --- a/src/main/java/net/minecraftforge/fml/ModLoader.java +++ b/src/main/java/net/minecraftforge/fml/ModLoader.java @@ -46,9 +46,9 @@ import net.minecraftforge.registries.ObjectHolderRegistry; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import java.io.IOException; import java.nio.file.Path; import java.util.*; +import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Collectors; @@ -101,6 +101,8 @@ public class ModLoader private final List loadingExceptions; private final List loadingWarnings; private GatherDataEvent.DataGeneratorConfig dataGeneratorConfig; + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + private Optional> statusConsumer = Optional.empty(); private ModLoader() { @@ -125,18 +127,24 @@ public class ModLoader } public void loadMods() { + 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()); + statusConsumer.ifPresent(c->c.accept("Mod setup: SETUP")); dispatchAndHandleError(LifecycleEventProvider.SETUP); + statusConsumer.ifPresent(c->c.accept("Mod setup: SIDED SETUP")); DistExecutor.runWhenOn(Dist.CLIENT, this::fireClientEvents); dispatchAndHandleError(LifecycleEventProvider.SIDED_SETUP); + statusConsumer.ifPresent(c->c.accept("Mod setup complete")); } public void gatherAndInitializeMods() { + 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()) { throw new LoadingFailedException(loadingExceptions); } + statusConsumer.ifPresent(c->c.accept("Building Mod List")); final List modContainers = loadingModList.getModFiles().stream(). map(ModFileInfo::getFile). map(mf -> buildMods(mf, launchClassLoader)). @@ -147,11 +155,15 @@ public class ModLoader throw new LoadingFailedException(loadingExceptions); } modList.setLoadedMods(modContainers); + statusConsumer.ifPresent(c->c.accept("Constructing mods")); dispatchAndHandleError(LifecycleEventProvider.CONSTRUCT); + statusConsumer.ifPresent(c->c.accept("Creating registries")); GameData.fireCreateRegistryEvents(LifecycleEventProvider.CREATE_REGISTRIES, this::dispatchAndHandleError); ObjectHolderRegistry.findObjectHolders(); CapabilityManager.INSTANCE.injectCapabilities(modList.getAllScanData()); + statusConsumer.ifPresent(c->c.accept("Populating registries")); GameData.fireRegistryEvents(rl->true, LifecycleEventProvider.LOAD_REGISTRIES, this::dispatchAndHandleError); + statusConsumer.ifPresent(c->c.accept("Early mod loading complete")); } private void dispatchAndHandleError(LifecycleEventProvider event) { @@ -207,11 +219,16 @@ public class ModLoader public void finishMods() { + statusConsumer.ifPresent(c->c.accept("Mod setup: ENQUEUE IMC")); dispatchAndHandleError(LifecycleEventProvider.ENQUEUE_IMC); + statusConsumer.ifPresent(c->c.accept("Mod setup: PROCESS IMC")); dispatchAndHandleError(LifecycleEventProvider.PROCESS_IMC); + statusConsumer.ifPresent(c->c.accept("Mod setup: Final completion")); dispatchAndHandleError(LifecycleEventProvider.COMPLETE); + statusConsumer.ifPresent(c->c.accept("Freezing data")); GameData.freezeData(); NetworkRegistry.lock(); + statusConsumer.ifPresent(c->c.accept("")); } public List getWarnings() @@ -237,4 +254,8 @@ public class ModLoader public Function getDataGeneratorEvent() { return mc -> new GatherDataEvent(mc, dataGeneratorConfig.makeGenerator(p->dataGeneratorConfig.getMods().size() == 1 ? p : p.resolve(mc.getModId()), dataGeneratorConfig.getMods().contains(mc.getModId())), dataGeneratorConfig); } + + public void setStatusConsumer(Consumer consumer) { + this.statusConsumer = Optional.ofNullable(consumer); + } } diff --git a/src/main/java/net/minecraftforge/fml/client/ClientModLoader.java b/src/main/java/net/minecraftforge/fml/client/ClientModLoader.java index 79f472ea05..0f3e2d3153 100644 --- a/src/main/java/net/minecraftforge/fml/client/ClientModLoader.java +++ b/src/main/java/net/minecraftforge/fml/client/ClientModLoader.java @@ -50,6 +50,7 @@ public class ClientModLoader private static boolean loading; private static Minecraft mc; private static LoadingFailedException error; + private static EarlyLoaderGUI earlyLoaderGUI; public static void begin(final Minecraft minecraft, final ResourcePackList defaultResourcePacks, final IReloadableResourceManager mcResourceManager, DownloadingPackFinder metadataSerializer) { @@ -57,6 +58,8 @@ public class ClientModLoader ClientModLoader.mc = minecraft; SidedProvider.setClient(()->minecraft); LogicalSidedProvider.setClient(()->minecraft); + earlyLoaderGUI = new EarlyLoaderGUI(minecraft.mainWindow); + ModLoader.get().setStatusConsumer(earlyLoaderGUI.getStatusConsumer()); createRunnableWithCatch(ModLoader.get()::gatherAndInitializeMods).run(); ResourcePackLoader.loadResourcePacks(defaultResourcePacks); mcResourceManager.addReloadListener(ClientModLoader::onreload); @@ -64,9 +67,9 @@ public class ClientModLoader } private static CompletableFuture onreload(final IFutureReloadListener.IStage stage, final IResourceManager resourceManager, final IProfiler prepareProfiler, final IProfiler executeProfiler, final Executor asyncExecutor, final Executor syncExecutor) { - return CompletableFuture.runAsync(createRunnableWithCatch(ModLoader.get()::loadMods), syncExecutor). + return CompletableFuture.runAsync(createRunnableWithCatch(ClientModLoader::startModLoading), syncExecutor). thenCompose(stage::markCompleteAwaitingOthers). - thenRunAsync(ClientModLoader::end); + thenRunAsync(ClientModLoader::finishModLoading, syncExecutor); } private static Runnable createRunnableWithCatch(Runnable r) { @@ -80,7 +83,11 @@ public class ClientModLoader }; } - public static void end() + private static void startModLoading() { + earlyLoaderGUI.handleElsewhere(); + createRunnableWithCatch(ModLoader.get()::loadMods).run(); + } + private static void finishModLoading() { createRunnableWithCatch(ModLoader.get()::finishMods).run(); loading = false; @@ -122,6 +129,9 @@ public class ClientModLoader } } + public static void renderProgressText() { + earlyLoaderGUI.renderFromGUI(); + } public static boolean isLoading() { return loading; diff --git a/src/main/java/net/minecraftforge/fml/client/EarlyLoaderGUI.java b/src/main/java/net/minecraftforge/fml/client/EarlyLoaderGUI.java new file mode 100644 index 0000000000..cbcccf5a93 --- /dev/null +++ b/src/main/java/net/minecraftforge/fml/client/EarlyLoaderGUI.java @@ -0,0 +1,72 @@ +package net.minecraftforge.fml.client; + +import com.mojang.blaze3d.platform.GlStateManager; +import net.minecraft.client.MainWindow; +import net.minecraft.client.Minecraft; +import org.lwjgl.opengl.GL11; +import org.lwjgl.stb.STBEasyFont; +import org.lwjgl.system.MemoryUtil; + +import java.nio.ByteBuffer; +import java.util.function.Consumer; + +public class EarlyLoaderGUI { + private final MainWindow window; + private String message; + private boolean handledElsewhere; + + public EarlyLoaderGUI(final MainWindow window) { + this.window = window; + GlStateManager.clearColor(1.0f, 1.0f, 1.0f, 1.0f); + GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT, Minecraft.IS_RUNNING_ON_MAC); + window.update(false); + } + + public Consumer getStatusConsumer() { + return this::update; + } + + private void update(final String message) { + this.message = message; + if (handledElsewhere) return; + doMatrix(); + + GlStateManager.clearColor(1.0f, 1.0f, 1.0f, 1.0f); + GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT, Minecraft.IS_RUNNING_ON_MAC); + renderMessage(); + window.update(false); + } + + public void handleElsewhere() { + this.handledElsewhere = true; + } + + void renderFromGUI() { + doMatrix(); + renderMessage(); + } + void renderMessage() { + GlStateManager.enableClientState(GL11.GL_VERTEX_ARRAY); + ByteBuffer charBuffer = MemoryUtil.memAlloc(this.message.length() * 270); + int quads = STBEasyFont.stb_easy_font_print(0, 0, this.message, null, charBuffer); + GlStateManager.vertexPointer(2, GL11.GL_FLOAT, 16, charBuffer); + + GlStateManager.color3f(0,0,0); + GlStateManager.pushMatrix(); + GlStateManager.translatef(10, window.getFramebufferHeight() - 50, 0); + GlStateManager.scalef(3, 3, 0); + GlStateManager.drawArrays(GL11.GL_QUADS, 0, quads * 4); + GlStateManager.popMatrix(); + + MemoryUtil.memFree(charBuffer); + } + + private void doMatrix() { + GlStateManager.clear(GL11.GL_DEPTH_BUFFER_BIT, Minecraft.IS_RUNNING_ON_MAC); + GlStateManager.matrixMode(GL11.GL_PROJECTION); + GlStateManager.loadIdentity(); + GlStateManager.ortho(0.0, window.getFramebufferWidth(), window.getFramebufferHeight(), 0.0, -1.0, 1.0); + GlStateManager.matrixMode(GL11.GL_MODELVIEW); + GlStateManager.loadIdentity(); + } +}