From 448d996a45f1b4cbe3180a86183f282f3e722b13 Mon Sep 17 00:00:00 2001 From: cpw Date: Sat, 22 Jun 2019 23:39:00 -0400 Subject: [PATCH] First pass of adding text to the loading progress UI. It deliberately uses the very primitive STB generated font, so can only render basic ASCII text, and also only renders pre-defined strings, as translations aren't available either. Signed-off-by: cpw --- .../gui/ResourceLoadProgressGui.java.patch | 10 +++ .../net/minecraftforge/fml/ModLoader.java | 23 +++++- .../fml/client/ClientModLoader.java | 16 ++++- .../fml/client/EarlyLoaderGUI.java | 72 +++++++++++++++++++ 4 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 patches/minecraft/net/minecraft/client/gui/ResourceLoadProgressGui.java.patch create mode 100644 src/main/java/net/minecraftforge/fml/client/EarlyLoaderGUI.java 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 000000000..1c59e480f --- /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 977af62c2..7dab12a31 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 79f472ea0..0f3e2d315 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 000000000..cbcccf5a9 --- /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(); + } +}