Remove legacy StartupProgress.
Implement properly scalable progress thanks to @gigaherz. Closes #5863. Implement API for pushing messages to the startup screen from mods. Add memory display. Signed-off-by: cpw <cpw+github@weeksfamily.ca>
This commit is contained in:
parent
943fedb073
commit
c8e5007913
26 changed files with 348 additions and 1526 deletions
|
@ -1,14 +0,0 @@
|
|||
--- a/com/mojang/blaze3d/platform/TextureUtil.java
|
||||
+++ b/com/mojang/blaze3d/platform/TextureUtil.java
|
||||
@@ -44,7 +44,10 @@
|
||||
}
|
||||
|
||||
public static void prepareImage(NativeImage.PixelFormatGLCode p_prepareImage_0_, int p_prepareImage_1_, int p_prepareImage_2_, int p_prepareImage_3_, int p_prepareImage_4_) {
|
||||
- bind(p_prepareImage_1_);
|
||||
+ synchronized (net.minecraftforge.fml.client.SplashProgress.class)
|
||||
+ {
|
||||
+ bind(p_prepareImage_1_);
|
||||
+ }
|
||||
if (p_prepareImage_2_ >= 0) {
|
||||
GlStateManager.texParameter(3553, 33085, p_prepareImage_2_);
|
||||
GlStateManager.texParameter(3553, 33082, 0);
|
|
@ -1,42 +1,6 @@
|
|||
--- a/net/minecraft/client/audio/SoundHandler.java
|
||||
+++ b/net/minecraft/client/audio/SoundHandler.java
|
||||
@@ -61,6 +61,7 @@
|
||||
SoundHandler.Loader soundhandler$loader = new SoundHandler.Loader();
|
||||
p_212854_2_.func_219894_a();
|
||||
|
||||
+ java.util.List<net.minecraft.util.Tuple<ResourceLocation, Runnable>> resources = new java.util.LinkedList<>();
|
||||
for(String s : p_212854_1_.func_199001_a()) {
|
||||
p_212854_2_.func_76320_a(s);
|
||||
|
||||
@@ -74,7 +75,9 @@
|
||||
p_212854_2_.func_219895_b("register");
|
||||
|
||||
for(Entry<String, SoundList> entry : map.entrySet()) {
|
||||
+ resources.add(new net.minecraft.util.Tuple<>(new ResourceLocation(s, entry.getKey()), () -> {
|
||||
soundhandler$loader.func_217944_a(new ResourceLocation(s, entry.getKey()), entry.getValue(), p_212854_1_);
|
||||
+ }));
|
||||
}
|
||||
|
||||
p_212854_2_.func_76319_b();
|
||||
@@ -91,6 +94,17 @@
|
||||
p_212854_2_.func_76319_b();
|
||||
}
|
||||
|
||||
+ net.minecraftforge.fml.common.progress.StartupProgressManager.start("Loading sounds", resources.size(), bar -> {
|
||||
+ resources.forEach(entry -> {
|
||||
+ bar.step(entry.func_76341_a().toString());
|
||||
+ try {
|
||||
+ entry.func_76340_b().run();
|
||||
+ } catch (RuntimeException e) {
|
||||
+ field_147698_b.warn("Invalid sounds.json", e);
|
||||
+ }
|
||||
+ });
|
||||
+ });
|
||||
+
|
||||
p_212854_2_.func_219897_b();
|
||||
return soundhandler$loader;
|
||||
}
|
||||
@@ -210,6 +224,11 @@
|
||||
@@ -210,6 +210,11 @@
|
||||
this.field_147694_f.func_195855_a(p_195478_1_, p_195478_2_);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
--- a/net/minecraft/client/gui/ResourceLoadProgressGui.java
|
||||
+++ b/net/minecraft/client/gui/ResourceLoadProgressGui.java
|
||||
@@ -83,6 +83,7 @@
|
||||
@@ -79,6 +79,7 @@
|
||||
this.blit(k1, i1, 0, 0, 256, 256);
|
||||
float f3 = this.field_212975_c.func_219555_b();
|
||||
this.field_212978_f = this.field_212978_f * 0.95F + f3 * 0.050000012F;
|
||||
+ net.minecraftforge.fml.client.ClientModLoader.renderProgressText();
|
||||
if (f < 1.0F) {
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -9,28 +9,19 @@
|
|||
private static final Comparator<Stitcher.Holder> field_217797_a = Comparator.<Stitcher.Holder, Integer>comparing((p_217793_0_) -> {
|
||||
return -p_217793_0_.field_94201_d;
|
||||
}).thenComparing((p_217795_0_) -> {
|
||||
@@ -50,15 +52,21 @@
|
||||
public void func_94305_f() {
|
||||
List<Stitcher.Holder> list = Lists.newArrayList(this.field_94319_a);
|
||||
list.sort(field_217797_a);
|
||||
+ try(net.minecraftforge.fml.common.progress.ProgressBar bar = net.minecraftforge.fml.common.progress.StartupProgressManager.start("Texture stitching", list.size())) {
|
||||
@@ -53,6 +55,12 @@
|
||||
|
||||
for(Stitcher.Holder stitcher$holder : list) {
|
||||
+ bar.step(stitcher$holder.field_98151_a.func_195668_m().toString());
|
||||
if (!this.func_94310_b(stitcher$holder)) {
|
||||
+ LOGGER.info(String.format("Unable to fit: %s - size: %dx%d - Maybe try a lower resolution resourcepack?", stitcher$holder.field_98151_a.func_195668_m(), stitcher$holder.field_98151_a.func_94211_a(), stitcher$holder.field_98151_a.func_94216_b()));
|
||||
+ for (Stitcher.Holder h : list)
|
||||
+ LOGGER.info(" {}", h);
|
||||
+ LOGGER.info(new net.minecraftforge.fml.loading.AdvancedLogMessageAdapter(sb->{
|
||||
+ sb.append("Unable to fit: ").append(stitcher$holder.field_98151_a.func_195668_m());
|
||||
+ sb.append(" - size: ").append(stitcher$holder.field_98151_a.func_94211_a()).append("x").append(stitcher$holder.field_98151_a.func_94216_b());
|
||||
+ sb.append(" - Maybe try a lower resolution resourcepack?\n");
|
||||
+ list.forEach(h-> sb.append("\t").append(h).append("\n"));
|
||||
+ }));
|
||||
throw new StitcherException(stitcher$holder.field_98151_a);
|
||||
}
|
||||
}
|
||||
|
||||
this.field_94318_c = MathHelper.func_151236_b(this.field_94318_c);
|
||||
this.field_94315_d = MathHelper.func_151236_b(this.field_94315_d);
|
||||
+ }; // Forge: end progress bar
|
||||
}
|
||||
|
||||
public List<TextureAtlasSprite> func_94309_g() {
|
||||
@@ -104,7 +112,7 @@
|
||||
boolean flag4 = flag2 && j != l;
|
||||
boolean flag;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
public boolean func_219533_b(ResourceLocation p_219533_1_) {
|
||||
IResourceManager iresourcemanager = this.field_199014_c.get(p_219533_1_.func_110624_b());
|
||||
return iresourcemanager != null ? iresourcemanager.func_219533_b(p_219533_1_) : false;
|
||||
@@ -118,18 +116,20 @@
|
||||
@@ -118,7 +116,6 @@
|
||||
return iasyncreloader;
|
||||
}
|
||||
|
||||
|
@ -24,17 +24,3 @@
|
|||
public IAsyncReloader func_219535_a(Executor p_219535_1_, Executor p_219535_2_, CompletableFuture<Unit> p_219535_3_) {
|
||||
return this.func_219538_b(p_219535_1_, p_219535_2_, this.field_219539_d, p_219535_3_);
|
||||
}
|
||||
|
||||
public IAsyncReloader func_219537_a(Executor p_219537_1_, Executor p_219537_2_, CompletableFuture<Unit> p_219537_3_, List<IResourcePack> p_219537_4_) {
|
||||
+ net.minecraftforge.fml.common.progress.StartupProgressManager.start("Loading Resources", p_219537_4_.size(), true, bar -> {
|
||||
this.func_199008_b();
|
||||
field_199012_a.info("Reloading ResourceManager: {}", p_219537_4_.stream().map(IResourcePack::func_195762_a).collect(Collectors.joining(", ")));
|
||||
|
||||
for(IResourcePack iresourcepack : p_219537_4_) {
|
||||
+ bar.step(iresourcepack.func_195762_a());
|
||||
this.func_199021_a(iresourcepack);
|
||||
}
|
||||
+ });
|
||||
|
||||
return this.func_219538_b(p_219537_1_, p_219537_2_, this.field_199015_d, p_219537_3_);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,22 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.loading;
|
||||
|
||||
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
|
||||
|
|
|
@ -1,3 +1,22 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.client.model;
|
||||
|
||||
import net.minecraft.client.renderer.texture.ISprite;
|
||||
|
|
|
@ -20,11 +20,7 @@
|
|||
package net.minecraftforge.common;
|
||||
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.fml.ExtensionPoint;
|
||||
import net.minecraftforge.fml.FMLWorldPersistenceHook;
|
||||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
import net.minecraftforge.fml.VersionChecker;
|
||||
import net.minecraftforge.fml.WorldPersistenceHooks;
|
||||
import net.minecraftforge.fml.*;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent;
|
||||
|
@ -103,6 +99,7 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
|
|||
modEventBus.register(ForgeConfig.class);
|
||||
// Forge does not display problems when the remote is not matching.
|
||||
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.DISPLAYTEST, ()-> Pair.of(()->"ANY", (remote, isServer)-> true));
|
||||
StartupMessageManager.addModMessage("Forge version "+ForgeVersion.getVersion());
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,3 +1,22 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.extensions;
|
||||
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
|
|
|
@ -1,3 +1,22 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.extensions;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
|
|
@ -1,3 +1,22 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.extensions;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
|
|
@ -41,7 +41,7 @@ public enum LifecycleEventProvider
|
|||
GATHERDATA(()->new GatherDataLifecycleEvent(ModLoadingStage.GATHERDATA), ModList.inlineDispatcher);
|
||||
|
||||
private final Supplier<? extends LifecycleEvent> event;
|
||||
private final EventHandler<LifecycleEvent, Consumer<List<ModLoadingException>>,Executor> eventDispatcher;
|
||||
private final EventHandler<LifecycleEvent, Consumer<List<ModLoadingException>>,Executor, Runnable> eventDispatcher;
|
||||
private Supplier<Event> customEventSupplier;
|
||||
private LifecycleEvent.Progression progression = LifecycleEvent.Progression.NEXT;
|
||||
|
||||
|
@ -50,7 +50,7 @@ public enum LifecycleEventProvider
|
|||
this(e, ModList.parallelDispatcher);
|
||||
}
|
||||
|
||||
LifecycleEventProvider(Supplier<? extends LifecycleEvent> e, EventHandler<LifecycleEvent, Consumer<List<ModLoadingException>>,Executor> eventDispatcher)
|
||||
LifecycleEventProvider(Supplier<? extends LifecycleEvent> e, EventHandler<LifecycleEvent, Consumer<List<ModLoadingException>>,Executor, Runnable> eventDispatcher)
|
||||
{
|
||||
this.event = e;
|
||||
this.eventDispatcher = eventDispatcher;
|
||||
|
@ -64,11 +64,11 @@ public enum LifecycleEventProvider
|
|||
this.progression = progression;
|
||||
}
|
||||
|
||||
public void dispatch(Consumer<List<ModLoadingException>> errorHandler, final Executor executor) {
|
||||
public void dispatch(Consumer<List<ModLoadingException>> errorHandler, final Executor executor, final Runnable ticker) {
|
||||
final LifecycleEvent lifecycleEvent = this.event.get();
|
||||
lifecycleEvent.setCustomEventSupplier(this.customEventSupplier);
|
||||
lifecycleEvent.changeProgression(this.progression);
|
||||
this.eventDispatcher.dispatchEvent(lifecycleEvent, errorHandler, executor);
|
||||
this.eventDispatcher.dispatchEvent(lifecycleEvent, errorHandler, executor, ticker);
|
||||
}
|
||||
|
||||
|
||||
|
@ -148,7 +148,7 @@ public enum LifecycleEventProvider
|
|||
}
|
||||
}
|
||||
|
||||
public interface EventHandler<T extends LifecycleEvent, U extends Consumer<? extends List<? super ModLoadingException>>, V extends Executor> {
|
||||
void dispatchEvent(T event, U exceptionHandler, V executor);
|
||||
public interface EventHandler<T extends LifecycleEvent, U extends Consumer<? extends List<? super ModLoadingException>>, V extends Executor, R extends Runnable> {
|
||||
void dispatchEvent(T event, U exceptionHandler, V executor, R ticker);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,10 +33,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.ForkJoinWorkerThread;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
@ -81,9 +78,9 @@ public class ModList
|
|||
return INSTANCE;
|
||||
}
|
||||
|
||||
static LifecycleEventProvider.EventHandler<LifecycleEventProvider.LifecycleEvent, Consumer<List<ModLoadingException>>, Executor> inlineDispatcher = (event, errors, executor) -> 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);
|
||||
|
||||
static LifecycleEventProvider.EventHandler<LifecycleEventProvider.LifecycleEvent, Consumer<List<ModLoadingException>>, Executor> parallelDispatcher = (event, errors, executor) -> ModList.get().dispatchParallelEvent(event, errors, executor);
|
||||
static LifecycleEventProvider.EventHandler<LifecycleEventProvider.LifecycleEvent, Consumer<List<ModLoadingException>>, Executor, Runnable> parallelDispatcher = (event, errors, executor, ticker) -> ModList.get().dispatchParallelEvent(event, errors, executor, ticker);
|
||||
|
||||
public static ModList get() {
|
||||
return INSTANCE;
|
||||
|
@ -113,13 +110,17 @@ public class ModList
|
|||
this.mods.forEach(m->m.transitionState(lifecycleEvent, errorHandler));
|
||||
FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.consumeLifecycleEvent(()->lifecycleEvent));
|
||||
}
|
||||
private void dispatchParallelEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent, final Consumer<List<ModLoadingException>> errorHandler, final Executor executor) {
|
||||
private void dispatchParallelEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent, final Consumer<List<ModLoadingException>> errorHandler, final Executor executor, final Runnable ticker) {
|
||||
LOGGER.debug(LOADING, "Dispatching parallel event {}", lifecycleEvent);
|
||||
FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.consumeLifecycleEvent(()->lifecycleEvent));
|
||||
DeferredWorkQueue.clear();
|
||||
try
|
||||
{
|
||||
modLoadingThreadPool.submit(()->this.mods.parallelStream().forEach(m->m.transitionState(lifecycleEvent, errorHandler))).get();
|
||||
final ForkJoinTask<?> parallelTask = modLoadingThreadPool.submit(() -> this.mods.parallelStream().forEach(m -> m.transitionState(lifecycleEvent, errorHandler)));
|
||||
while (ticker != null && !parallelTask.isDone()) {
|
||||
executor.execute(ticker);
|
||||
}
|
||||
parallelTask.get();
|
||||
}
|
||||
catch (InterruptedException | ExecutionException e)
|
||||
{
|
||||
|
|
|
@ -102,7 +102,7 @@ public class ModLoader
|
|||
private final List<ModLoadingWarning> loadingWarnings;
|
||||
private GatherDataEvent.DataGeneratorConfig dataGeneratorConfig;
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
private Optional<Consumer<String>> statusConsumer = Optional.empty();
|
||||
private final Optional<Consumer<String>> statusConsumer = StartupMessageManager.modLoaderConsumer();
|
||||
|
||||
private ModLoader()
|
||||
{
|
||||
|
@ -127,15 +127,15 @@ public class ModLoader
|
|||
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, mainThreadExecutor);
|
||||
dispatchAndHandleError(LifecycleEventProvider.SETUP, mainThreadExecutor, null);
|
||||
statusConsumer.ifPresent(c->c.accept("Mod setup: SIDED SETUP"));
|
||||
mainThreadExecutor.execute(()->preSidedRunnable.accept(c->ModList.get().forEachModContainer((mi,mc)->mc.acceptEvent(c.get()))));
|
||||
dispatchAndHandleError(LifecycleEventProvider.SIDED_SETUP, mainThreadExecutor);
|
||||
dispatchAndHandleError(LifecycleEventProvider.SIDED_SETUP, mainThreadExecutor, null);
|
||||
mainThreadExecutor.execute(()->postSidedRunnable.accept(c->ModList.get().forEachModContainer((mi,mc)->mc.acceptEvent(c.get()))));
|
||||
statusConsumer.ifPresent(c->c.accept("Mod setup complete"));
|
||||
}
|
||||
|
||||
public void gatherAndInitializeMods() {
|
||||
public void gatherAndInitializeMods(final Runnable 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()) {
|
||||
|
@ -155,22 +155,22 @@ public class ModLoader
|
|||
throw new LoadingFailedException(loadingExceptions);
|
||||
}
|
||||
modList.setLoadedMods(modContainers);
|
||||
statusConsumer.ifPresent(c->c.accept("Constructing mods"));
|
||||
dispatchAndHandleError(LifecycleEventProvider.CONSTRUCT, Runnable::run);
|
||||
statusConsumer.ifPresent(c->c.accept(String.format("Constructing %d mods", modList.size())));
|
||||
dispatchAndHandleError(LifecycleEventProvider.CONSTRUCT, Runnable::run, ticker);
|
||||
statusConsumer.ifPresent(c->c.accept("Creating registries"));
|
||||
GameData.fireCreateRegistryEvents(LifecycleEventProvider.CREATE_REGISTRIES, event -> dispatchAndHandleError(event, Runnable::run));
|
||||
GameData.fireCreateRegistryEvents(LifecycleEventProvider.CREATE_REGISTRIES, event -> dispatchAndHandleError(event, Runnable::run, 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));
|
||||
GameData.fireRegistryEvents(rl->true, LifecycleEventProvider.LOAD_REGISTRIES, event -> dispatchAndHandleError(event, Runnable::run, ticker));
|
||||
statusConsumer.ifPresent(c->c.accept("Early mod loading complete"));
|
||||
}
|
||||
|
||||
private void dispatchAndHandleError(LifecycleEventProvider event, Executor executor) {
|
||||
private void dispatchAndHandleError(LifecycleEventProvider event, Executor executor, final Runnable ticker) {
|
||||
if (!loadingExceptions.isEmpty()) {
|
||||
LOGGER.error(LOADING,"Skipping lifecycle event {}, {} errors found.", event, loadingExceptions.size());
|
||||
} else {
|
||||
event.dispatch(this::accumulateErrors, executor);
|
||||
event.dispatch(this::accumulateErrors, executor, ticker);
|
||||
}
|
||||
if (!loadingExceptions.isEmpty()) {
|
||||
LOGGER.fatal(LOADING,"Failed to complete lifecycle event {}, {} errors found", event, loadingExceptions.size());
|
||||
|
@ -220,15 +220,15 @@ public class ModLoader
|
|||
public void finishMods(Executor mainThreadExecutor)
|
||||
{
|
||||
statusConsumer.ifPresent(c->c.accept("Mod setup: ENQUEUE IMC"));
|
||||
dispatchAndHandleError(LifecycleEventProvider.ENQUEUE_IMC, mainThreadExecutor);
|
||||
dispatchAndHandleError(LifecycleEventProvider.ENQUEUE_IMC, mainThreadExecutor, null);
|
||||
statusConsumer.ifPresent(c->c.accept("Mod setup: PROCESS IMC"));
|
||||
dispatchAndHandleError(LifecycleEventProvider.PROCESS_IMC, mainThreadExecutor);
|
||||
dispatchAndHandleError(LifecycleEventProvider.PROCESS_IMC, mainThreadExecutor, null);
|
||||
statusConsumer.ifPresent(c->c.accept("Mod setup: Final completion"));
|
||||
dispatchAndHandleError(LifecycleEventProvider.COMPLETE, mainThreadExecutor);
|
||||
dispatchAndHandleError(LifecycleEventProvider.COMPLETE, mainThreadExecutor, null);
|
||||
statusConsumer.ifPresent(c->c.accept("Freezing data"));
|
||||
GameData.freezeData();
|
||||
NetworkRegistry.lock();
|
||||
statusConsumer.ifPresent(c->c.accept(""));
|
||||
statusConsumer.ifPresent(c->c.accept(String.format("Mod loading complete - %d mods loaded", ModList.get().size())));
|
||||
}
|
||||
|
||||
public List<ModLoadingWarning> getWarnings()
|
||||
|
@ -246,16 +246,12 @@ public class ModLoader
|
|||
LOGGER.info("Initializing Data Gatherer for mods {}", mods);
|
||||
Bootstrap.register();
|
||||
dataGeneratorConfig = new GatherDataEvent.DataGeneratorConfig(mods, path, inputs, serverGenerators, clientGenerators, devToolGenerators, reportsGenerator, structureValidator);
|
||||
gatherAndInitializeMods();
|
||||
dispatchAndHandleError(LifecycleEventProvider.GATHERDATA, Runnable::run);
|
||||
gatherAndInitializeMods(null);
|
||||
dispatchAndHandleError(LifecycleEventProvider.GATHERDATA, Runnable::run, null);
|
||||
dataGeneratorConfig.runAll();
|
||||
}
|
||||
|
||||
public Function<ModContainer, ModLifecycleEvent> 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<String> consumer) {
|
||||
this.statusConsumer = Optional.ofNullable(consumer);
|
||||
}
|
||||
}
|
||||
|
|
103
src/main/java/net/minecraftforge/fml/StartupMessageManager.java
Normal file
103
src/main/java/net/minecraftforge/fml/StartupMessageManager.java
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml;
|
||||
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class StartupMessageManager {
|
||||
private static final EnumMap<MessageType, List<Message>> messages = new EnumMap<>(MessageType.class);
|
||||
static {
|
||||
Arrays.stream(MessageType.values()).forEach(mt->messages.computeIfAbsent(mt, k->new CopyOnWriteArrayList<>()));
|
||||
}
|
||||
|
||||
public static List<Pair<Integer,Message>> getMessages() {
|
||||
final long ts = System.nanoTime();
|
||||
return messages.values().stream().flatMap(Collection::stream).
|
||||
sorted(Comparator.comparingLong(Message::getTimestamp).thenComparing(Message::getText).reversed()).
|
||||
map(m -> Pair.of((int) ((ts - m.timestamp) / 1e6), m)).
|
||||
collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static class Message {
|
||||
private final String text;
|
||||
private final MessageType type;
|
||||
private final long timestamp;
|
||||
|
||||
public Message(final String text, final MessageType type) {
|
||||
this.text = text;
|
||||
this.type = type;
|
||||
this.timestamp = System.nanoTime();
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
MessageType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public float[] getTypeColour() {
|
||||
return type.colour();
|
||||
}
|
||||
}
|
||||
|
||||
enum MessageType {
|
||||
MC(0.0f, 0.0f, 0.0f),
|
||||
ML(0.0f, 0.0f, 0.5f),
|
||||
MOD(0.5f, 0.0f, 0.0f);
|
||||
|
||||
private final float[] colour;
|
||||
|
||||
MessageType(final float r, final float g, final float b) {
|
||||
colour = new float[] {r,g,b};
|
||||
}
|
||||
|
||||
public float[] colour() {
|
||||
return colour;
|
||||
}
|
||||
}
|
||||
|
||||
public static void addModMessage(final String message) {
|
||||
final String safeMessage = Ascii.truncate(CharMatcher.ascii().retainFrom(message),80,"~");
|
||||
final List<Message> messages = StartupMessageManager.messages.get(MessageType.MOD);
|
||||
messages.subList(0, Math.max(0, messages.size() - 20)).clear();
|
||||
messages.add(new Message(safeMessage, MessageType.MOD));
|
||||
}
|
||||
|
||||
static Optional<Consumer<String>> modLoaderConsumer() {
|
||||
return Optional.of(s-> messages.get(MessageType.ML).add(new Message(s, MessageType.ML)));
|
||||
}
|
||||
|
||||
static Optional<Consumer<String>> mcLoaderConsumer() {
|
||||
return Optional.of(s-> messages.get(MessageType.MC).add(new Message(s, MessageType.MC)));
|
||||
}
|
||||
}
|
|
@ -64,8 +64,7 @@ public class ClientModLoader
|
|||
SidedProvider.setClient(()->minecraft);
|
||||
LogicalSidedProvider.setClient(()->minecraft);
|
||||
earlyLoaderGUI = new EarlyLoaderGUI(minecraft.mainWindow);
|
||||
ModLoader.get().setStatusConsumer(earlyLoaderGUI.getStatusConsumer());
|
||||
createRunnableWithCatch(ModLoader.get()::gatherAndInitializeMods).run();
|
||||
createRunnableWithCatch(() -> ModLoader.get().gatherAndInitializeMods(earlyLoaderGUI::renderTick)).run();
|
||||
ResourcePackLoader.loadResourcePacks(defaultResourcePacks);
|
||||
mcResourceManager.addReloadListener(ClientModLoader::onreload);
|
||||
mcResourceManager.addReloadListener(BrandingControl.resourceManagerReloadListener());
|
||||
|
|
|
@ -1,18 +1,48 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.client;
|
||||
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import net.minecraft.client.MainWindow;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraftforge.fml.StartupMessageManager;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
import org.lwjgl.stb.STBEasyFont;
|
||||
import org.lwjgl.stb.STBImage;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryMXBean;
|
||||
import java.lang.management.MemoryUsage;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class EarlyLoaderGUI {
|
||||
private final MainWindow window;
|
||||
private String message;
|
||||
private boolean handledElsewhere;
|
||||
|
||||
public EarlyLoaderGUI(final MainWindow window) {
|
||||
|
@ -22,51 +52,69 @@ public class EarlyLoaderGUI {
|
|||
window.update(false);
|
||||
}
|
||||
|
||||
public Consumer<String> 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();
|
||||
renderMessages();
|
||||
}
|
||||
void renderMessage() {
|
||||
|
||||
void renderTick() {
|
||||
if (handledElsewhere) return;
|
||||
int guiScale = window.func_216521_a(0, false);
|
||||
window.func_216525_a(guiScale);
|
||||
|
||||
GlStateManager.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT, Minecraft.IS_RUNNING_ON_MAC);
|
||||
window.func_216522_a(Minecraft.IS_RUNNING_ON_MAC);
|
||||
renderMessages();
|
||||
window.update(false);
|
||||
}
|
||||
|
||||
private void renderMessages() {
|
||||
List<Pair<Integer, StartupMessageManager.Message>> messages = StartupMessageManager.getMessages();
|
||||
for (int i = 0; i < messages.size(); i++) {
|
||||
final Pair<Integer, StartupMessageManager.Message> pair = messages.get(i);
|
||||
final float fade = MathHelper.clamp((4000.0f - (float) pair.getLeft() - ( i - 4 ) * 1000.0f) / 5000.0f, 0.0f, 1.0f);
|
||||
if (fade <0.01f) continue;
|
||||
StartupMessageManager.Message msg = pair.getRight();
|
||||
renderMessage(msg.getText(), msg.getTypeColour(), i, fade);
|
||||
}
|
||||
renderMemoryInfo();
|
||||
}
|
||||
|
||||
private static final float[] memorycolour = new float[] { 0.0f, 0.0f, 0.0f};
|
||||
|
||||
private void renderMemoryInfo() {
|
||||
final MemoryUsage heapusage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
|
||||
final MemoryUsage offheapusage = ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage();
|
||||
final float pctmemory = (float) heapusage.getUsed() / heapusage.getMax();
|
||||
String memory = String.format("Memory Heap: %d / %d MB (%.1f%%) OffHeap: %d MB", heapusage.getUsed() >> 20, heapusage.getMax() >> 20, pctmemory * 100.0, offheapusage.getUsed() >> 20);
|
||||
|
||||
final int i = MathHelper.hsvToRGB((1.0f - (float)Math.pow(pctmemory, 1.5f)) / 3f, 1.0f, 0.5f);
|
||||
memorycolour[2] = ((i) & 0xFF) / 255.0f;
|
||||
memorycolour[1] = ((i >> 8 ) & 0xFF) / 255.0f;
|
||||
memorycolour[0] = ((i >> 16 ) & 0xFF) / 255.0f;
|
||||
renderMessage(memory, memorycolour, 21, 1.0f);
|
||||
}
|
||||
|
||||
void renderMessage(final String message, final float[] colour, int line, float alpha) {
|
||||
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);
|
||||
ByteBuffer charBuffer = MemoryUtil.memAlloc(message.length() * 270);
|
||||
int quads = STBEasyFont.stb_easy_font_print(0, 0, message, null, charBuffer);
|
||||
GlStateManager.vertexPointer(2, GL11.GL_FLOAT, 16, charBuffer);
|
||||
|
||||
GlStateManager.color3f(0,0,0);
|
||||
GlStateManager.enableBlend();
|
||||
GL14.glBlendColor(0,0,0, alpha);
|
||||
GlStateManager.blendFunc(GlStateManager.SourceFactor.CONSTANT_ALPHA, GlStateManager.DestFactor.ONE_MINUS_CONSTANT_ALPHA);
|
||||
GlStateManager.color3f(colour[0],colour[1],colour[2]);
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translatef(10, window.getFramebufferHeight() - 50, 0);
|
||||
GlStateManager.scalef(3, 3, 0);
|
||||
GlStateManager.translatef(10, window.getScaledHeight() - 15 - line * 10, 0);
|
||||
GlStateManager.scalef(1, 1, 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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.client;
|
||||
|
||||
public class FMLClientConfig
|
||||
{
|
||||
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.client;
|
||||
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
public interface IDisplayableError
|
||||
{
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
Screen createGui();
|
||||
}
|
|
@ -1,987 +0,0 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.client;
|
||||
/*
|
||||
import static net.minecraftforge.fml.Logging.SPLASH;
|
||||
import static net.minecraftforge.fml.Logging.fmlLog;
|
||||
import static org.lwjgl.opengl.GL11.*;
|
||||
import static org.lwjgl.opengl.GL12.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Iterator;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
|
||||
import com.google.common.base.CharMatcher;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.texture.TextureManager;
|
||||
import net.minecraft.client.resources.DefaultResourcePack;
|
||||
import net.minecraft.client.resources.FileResourcePack;
|
||||
import net.minecraft.client.resources.FolderResourcePack;
|
||||
import net.minecraft.client.resources.IResource;
|
||||
import net.minecraft.client.resources.IResourcePack;
|
||||
import net.minecraft.client.resources.SimpleResource;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.CrashReportExtender;
|
||||
import net.minecraftforge.fml.common.EnhancedRuntimeException;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
import net.minecraftforge.fml.common.ICrashCallable;
|
||||
import net.minecraftforge.fml.common.ProgressManager;
|
||||
import net.minecraftforge.fml.common.ProgressManager.ProgressBar;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.LWJGLException;
|
||||
import org.lwjgl.LWJGLUtil;
|
||||
import org.lwjgl.opengl.Display;
|
||||
import org.lwjgl.opengl.Drawable;
|
||||
import org.lwjgl.opengl.SharedDrawable;
|
||||
import org.lwjgl.util.glu.GLU;
|
||||
|
||||
/**
|
||||
* Not a fully fleshed out API, may change in future MC versions.
|
||||
* However feel free to use and suggest additions.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class SplashProgress
|
||||
{
|
||||
/*
|
||||
private static Drawable d;
|
||||
private static volatile boolean pause = false;
|
||||
private static volatile boolean done = false;
|
||||
private static Thread thread;
|
||||
private static volatile Throwable threadError;
|
||||
private static int angle = 0;
|
||||
private static final Lock lock = new ReentrantLock(true);
|
||||
private static SplashFontRenderer fontRenderer;
|
||||
|
||||
private static final IResourcePack mcPack = Minecraft.getMinecraft().mcDefaultResourcePack;
|
||||
private static final IResourcePack fmlPack = mcPack;
|
||||
private static IResourcePack miscPack;
|
||||
|
||||
private static Texture fontTexture;
|
||||
private static Texture logoTexture;
|
||||
private static Texture forgeTexture;
|
||||
|
||||
private static Properties config;
|
||||
|
||||
private static boolean enabled;
|
||||
private static boolean rotate;
|
||||
private static int logoOffset;
|
||||
private static int backgroundColor;
|
||||
private static int fontColor;
|
||||
private static int barBorderColor;
|
||||
private static int barColor;
|
||||
private static int barBackgroundColor;
|
||||
private static boolean showMemory;
|
||||
private static int memoryGoodColor;
|
||||
private static int memoryWarnColor;
|
||||
private static int memoryLowColor;
|
||||
private static float memoryColorPercent;
|
||||
private static long memoryColorChangeTime;
|
||||
static boolean isDisplayVSyncForced = false;
|
||||
private static final int TIMING_FRAME_COUNT = 200;
|
||||
private static final int TIMING_FRAME_THRESHOLD = TIMING_FRAME_COUNT * 5 * 1000000; // 5 ms per frame, scaled to nanos
|
||||
|
||||
private static final Semaphore mutex = new Semaphore(1);
|
||||
*/
|
||||
|
||||
public static void processMessages() {
|
||||
/*
|
||||
// workaround for windows requiring messages being processed on the main thread
|
||||
if (LWJGLUtil.getPlatform() != LWJGLUtil.PLATFORM_WINDOWS) return null;
|
||||
// If we can't grab the mutex, the update call is blocked, probably in native code, just skip it and carry on
|
||||
// We'll get another go next time
|
||||
if (!SplashProgress.mutex.tryAcquire()) return null;
|
||||
Display.processMessages();
|
||||
SplashProgress.mutex.release();
|
||||
*/
|
||||
}
|
||||
/*
|
||||
private static String getString(String name, String def)
|
||||
{
|
||||
String value = config.getProperty(name, def);
|
||||
config.setProperty(name, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
private static boolean getBool(String name, boolean def)
|
||||
{
|
||||
return Boolean.parseBoolean(getString(name, Boolean.toString(def)));
|
||||
}
|
||||
|
||||
private static int getInt(String name, int def)
|
||||
{
|
||||
return Integer.decode(getString(name, Integer.toString(def)));
|
||||
}
|
||||
|
||||
private static int getHex(String name, int def)
|
||||
{
|
||||
return Integer.decode(getString(name, "0x" + Integer.toString(def, 16).toUpperCase()));
|
||||
}
|
||||
|
||||
public static void start()
|
||||
{
|
||||
File configFile = new File(Minecraft.getMinecraft().mcDataDir, "config/splash.properties");
|
||||
|
||||
File parent = configFile.getParentFile();
|
||||
if (!parent.exists())
|
||||
parent.mkdirs();
|
||||
|
||||
config = new Properties();
|
||||
try (Reader r = new InputStreamReader(new FileInputStream(configFile), StandardCharsets.UTF_8))
|
||||
{
|
||||
config.load(r);
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
fmlLog.info(SPLASH, "Could not load splash.properties, will create a default one");
|
||||
}
|
||||
|
||||
enabled = getBool("enabled", true);
|
||||
rotate = getBool("rotate", false);
|
||||
showMemory = getBool("showMemory", true);
|
||||
logoOffset = getInt("logoOffset", 0);
|
||||
backgroundColor = getHex("background", 0xFFFFFF);
|
||||
fontColor = getHex("font", 0x000000);
|
||||
barBorderColor = getHex("barBorder", 0xC0C0C0);
|
||||
barColor = getHex("bar", 0xCB3D35);
|
||||
barBackgroundColor = getHex("barBackground", 0xFFFFFF);
|
||||
memoryGoodColor = getHex("memoryGood", 0x78CB34);
|
||||
memoryWarnColor = getHex("memoryWarn", 0xE6E84A);
|
||||
memoryLowColor = getHex("memoryLow", 0xE42F2F);
|
||||
|
||||
final ResourceLocation fontLoc = new ResourceLocation(getString("fontTexture", "textures/font/ascii.png"));
|
||||
final ResourceLocation logoLoc = new ResourceLocation("textures/gui/title/mojang.png");
|
||||
final ResourceLocation forgeLoc = new ResourceLocation(getString("forgeTexture", "fml:textures/gui/forge.png"));
|
||||
final ResourceLocation forgeFallbackLoc = new ResourceLocation("fml:textures/gui/forge.png");
|
||||
|
||||
File miscPackFile = new File(Minecraft.getMinecraft().mcDataDir, getString("resourcePackPath", "resources"));
|
||||
|
||||
try (Writer w = new OutputStreamWriter(new FileOutputStream(configFile), StandardCharsets.UTF_8))
|
||||
{
|
||||
config.store(w, "Splash screen properties");
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
LOGGER.error("Could not save the splash.properties file", e);
|
||||
}
|
||||
|
||||
miscPack = createResourcePack(miscPackFile);
|
||||
|
||||
if(!enabled) return;
|
||||
// getting debug info out of the way, while we still can
|
||||
CrashReportExtender.registerCrashCallable(new ICrashCallable()
|
||||
{
|
||||
@Override
|
||||
public String call() throws Exception
|
||||
{
|
||||
return "' Vendor: '" + glGetString(GL_VENDOR) +
|
||||
"' Version: '" + glGetString(GL_VERSION) +
|
||||
"' Renderer: '" + glGetString(GL_RENDERER) +
|
||||
"'";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel()
|
||||
{
|
||||
return "GL info";
|
||||
}
|
||||
});
|
||||
CrashReport report = CrashReport.makeCrashReport(new Throwable(), "Loading screen debug info");
|
||||
StringBuilder systemDetailsBuilder = new StringBuilder();
|
||||
report.getCategory().appendToStringBuilder(systemDetailsBuilder);
|
||||
fmlLog.info(SPLASH, systemDetailsBuilder.toString());
|
||||
|
||||
try
|
||||
{
|
||||
d = new SharedDrawable(Display.getDrawable());
|
||||
Display.getDrawable().releaseContext();
|
||||
d.makeCurrent();
|
||||
}
|
||||
catch (LWJGLException e)
|
||||
{
|
||||
LOGGER.error("Error starting SplashProgress:", e);
|
||||
disableSplash(e);
|
||||
}
|
||||
|
||||
//Call this ASAP if splash is enabled so that threading doesn't cause issues later
|
||||
getMaxTextureSize();
|
||||
|
||||
//Thread mainThread = Thread.currentThread();
|
||||
thread = new Thread(new Runnable()
|
||||
{
|
||||
private final int barWidth = 400;
|
||||
private final int barHeight = 20;
|
||||
private final int textHeight2 = 20;
|
||||
private final int barOffset = 55;
|
||||
private long updateTiming;
|
||||
private long framecount;
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
setGL();
|
||||
fontTexture = new Texture(fontLoc, null);
|
||||
logoTexture = new Texture(logoLoc, null, false);
|
||||
forgeTexture = new Texture(forgeLoc, forgeFallbackLoc);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
fontRenderer = new SplashFontRenderer();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
while(!done)
|
||||
{
|
||||
framecount++;
|
||||
ProgressBar first = null, penult = null, last = null;
|
||||
Iterator<ProgressBar> i = ProgressManager.barIterator();
|
||||
while(i.hasNext())
|
||||
{
|
||||
if(first == null) first = i.next();
|
||||
else
|
||||
{
|
||||
penult = last;
|
||||
last = i.next();
|
||||
}
|
||||
}
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// matrix setup
|
||||
int w = Display.getWidth();
|
||||
int h = Display.getHeight();
|
||||
glViewport(0, 0, w, h);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(320 - w/2, 320 + w/2, 240 + h/2, 240 - h/2, -1, 1);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
// mojang logo
|
||||
setColor(backgroundColor);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
logoTexture.bind();
|
||||
glBegin(GL_QUADS);
|
||||
logoTexture.texCoord(0, 0, 0);
|
||||
glVertex2f(320 - 256, 240 - 256);
|
||||
logoTexture.texCoord(0, 0, 1);
|
||||
glVertex2f(320 - 256, 240 + 256);
|
||||
logoTexture.texCoord(0, 1, 1);
|
||||
glVertex2f(320 + 256, 240 + 256);
|
||||
logoTexture.texCoord(0, 1, 0);
|
||||
glVertex2f(320 + 256, 240 - 256);
|
||||
glEnd();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
// memory usage
|
||||
if (showMemory)
|
||||
{
|
||||
glPushMatrix();
|
||||
glTranslatef(320 - (float) barWidth / 2, 20, 0);
|
||||
drawMemoryBar();
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
// bars
|
||||
if(first != null)
|
||||
{
|
||||
glPushMatrix();
|
||||
glTranslatef(320 - (float)barWidth / 2, 310, 0);
|
||||
drawBar(first);
|
||||
if(penult != null)
|
||||
{
|
||||
glTranslatef(0, barOffset, 0);
|
||||
drawBar(penult);
|
||||
}
|
||||
if(last != null)
|
||||
{
|
||||
glTranslatef(0, barOffset, 0);
|
||||
drawBar(last);
|
||||
}
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
angle += 1;
|
||||
|
||||
// forge logo
|
||||
glColor4f(1, 1, 1, 1);
|
||||
float fw = (float)forgeTexture.getWidth() / 2;
|
||||
float fh = (float)forgeTexture.getHeight() / 2;
|
||||
if(rotate)
|
||||
{
|
||||
float sh = Math.max(fw, fh);
|
||||
glTranslatef(320 + w/2 - sh - logoOffset, 240 + h/2 - sh - logoOffset, 0);
|
||||
glRotatef(angle, 0, 0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTranslatef(320 + w/2 - fw - logoOffset, 240 + h/2 - fh - logoOffset, 0);
|
||||
}
|
||||
int f = (angle / 5) % forgeTexture.getFrames();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
forgeTexture.bind();
|
||||
glBegin(GL_QUADS);
|
||||
forgeTexture.texCoord(f, 0, 0);
|
||||
glVertex2f(-fw, -fh);
|
||||
forgeTexture.texCoord(f, 0, 1);
|
||||
glVertex2f(-fw, fh);
|
||||
forgeTexture.texCoord(f, 1, 1);
|
||||
glVertex2f(fw, fh);
|
||||
forgeTexture.texCoord(f, 1, 0);
|
||||
glVertex2f(fw, -fh);
|
||||
glEnd();
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
// We use mutex to indicate safely to the main thread that we're taking the display global lock
|
||||
// So the main thread can skip processing messages while we're updating.
|
||||
// There are system setups where this call can pause for a while, because the GL implementation
|
||||
// is trying to impose a framerate or other thing is occurring. Without the mutex, the main
|
||||
// thread would delay waiting for the same global display lock
|
||||
mutex.acquireUninterruptibly();
|
||||
long updateStart = System.nanoTime();
|
||||
Display.update();
|
||||
// As soon as we're done, we release the mutex. The other thread can now ping the processmessages
|
||||
// call as often as it wants until we get get back here again
|
||||
long dur = System.nanoTime() - updateStart;
|
||||
if (framecount < TIMING_FRAME_COUNT) {
|
||||
updateTiming += dur;
|
||||
}
|
||||
mutex.release();
|
||||
if(pause)
|
||||
{
|
||||
clearGL();
|
||||
setGL();
|
||||
}
|
||||
// Such a hack - if the time taken is greater than 10 milliseconds, we're gonna guess that we're on a
|
||||
// system where vsync is forced through the swapBuffers call - so we have to force a sleep and let the
|
||||
// loading thread have a turn - some badly designed mods access Keyboard and therefore GlobalLock.lock
|
||||
// during splash screen, and mutex against the above Display.update call as a result.
|
||||
// 4 milliseconds is a guess - but it should be enough to trigger in most circumstances. (Maybe if
|
||||
// 240FPS is possible, this won't fire?)
|
||||
if (framecount >= TIMING_FRAME_COUNT && updateTiming > TIMING_FRAME_THRESHOLD) {
|
||||
if (!isDisplayVSyncForced)
|
||||
{
|
||||
isDisplayVSyncForced = true;
|
||||
fmlLog.info(SPLASH,"Using alternative sync timing : {} frames of Display.update took {} nanos", TIMING_FRAME_COUNT, updateTiming);
|
||||
}
|
||||
try { Thread.sleep(16); } catch (InterruptedException ie) {}
|
||||
} else
|
||||
{
|
||||
if (framecount ==TIMING_FRAME_COUNT) {
|
||||
fmlLog.info("Using sync timing. {} frames of Display.update took {} nanos", TIMING_FRAME_COUNT, updateTiming);
|
||||
}
|
||||
Display.sync(100);
|
||||
}
|
||||
}
|
||||
clearGL();
|
||||
}
|
||||
|
||||
private void setColor(int color)
|
||||
{
|
||||
glColor3ub((byte)((color >> 16) & 0xFF), (byte)((color >> 8) & 0xFF), (byte)(color & 0xFF));
|
||||
}
|
||||
|
||||
private void drawBox(int w, int h)
|
||||
{
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2f(0, 0);
|
||||
glVertex2f(0, h);
|
||||
glVertex2f(w, h);
|
||||
glVertex2f(w, 0);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
private void drawBar(ProgressBar b)
|
||||
{
|
||||
glPushMatrix();
|
||||
// title - message
|
||||
setColor(fontColor);
|
||||
glScalef(2, 2, 1);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
fontRenderer.drawString(b.getTitle() + " - " + b.getMessage(), 0, 0, 0x000000);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glPopMatrix();
|
||||
// border
|
||||
glPushMatrix();
|
||||
glTranslatef(0, textHeight2, 0);
|
||||
setColor(barBorderColor);
|
||||
drawBox(barWidth, barHeight);
|
||||
// interior
|
||||
setColor(barBackgroundColor);
|
||||
glTranslatef(1, 1, 0);
|
||||
drawBox(barWidth - 2, barHeight - 2);
|
||||
// slidy part
|
||||
setColor(barColor);
|
||||
int step = b.getStep();
|
||||
drawBox((barWidth - 2) * (step + 1) / (b.getTotalSteps() + 1), barHeight - 2); // Step can sometimes be 0.
|
||||
// progress text
|
||||
String progress = "" + step + "/" + b.getTotalSteps();
|
||||
glTranslatef(((float)barWidth - 2) / 2 - fontRenderer.getStringWidth(progress), 2, 0);
|
||||
setColor(fontColor);
|
||||
glScalef(2, 2, 1);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
fontRenderer.drawString(progress, 0, 0, 0x000000);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
private void drawMemoryBar() {
|
||||
int maxMemory = bytesToMb(Runtime.getRuntime().maxMemory());
|
||||
int totalMemory = bytesToMb(Runtime.getRuntime().totalMemory());
|
||||
int freeMemory = bytesToMb(Runtime.getRuntime().freeMemory());
|
||||
int usedMemory = totalMemory - freeMemory;
|
||||
float usedMemoryPercent = usedMemory / (float) maxMemory;
|
||||
|
||||
glPushMatrix();
|
||||
// title - message
|
||||
setColor(fontColor);
|
||||
glScalef(2, 2, 1);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
fontRenderer.drawString("Memory Used / Total", 0, 0, 0x000000);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glPopMatrix();
|
||||
// border
|
||||
glPushMatrix();
|
||||
glTranslatef(0, textHeight2, 0);
|
||||
setColor(barBorderColor);
|
||||
drawBox(barWidth, barHeight);
|
||||
// interior
|
||||
setColor(barBackgroundColor);
|
||||
glTranslatef(1, 1, 0);
|
||||
drawBox(barWidth - 2, barHeight - 2);
|
||||
// slidy part
|
||||
|
||||
long time = System.currentTimeMillis();
|
||||
if (usedMemoryPercent > memoryColorPercent || (time - memoryColorChangeTime > 1000))
|
||||
{
|
||||
memoryColorChangeTime = time;
|
||||
memoryColorPercent = usedMemoryPercent;
|
||||
}
|
||||
|
||||
int memoryBarColor;
|
||||
if (memoryColorPercent < 0.75f)
|
||||
{
|
||||
memoryBarColor = memoryGoodColor;
|
||||
}
|
||||
else if (memoryColorPercent < 0.85f)
|
||||
{
|
||||
memoryBarColor = memoryWarnColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
memoryBarColor = memoryLowColor;
|
||||
}
|
||||
setColor(memoryLowColor);
|
||||
glPushMatrix();
|
||||
glTranslatef((barWidth - 2) * (totalMemory) / (maxMemory) - 2, 0, 0);
|
||||
drawBox(2, barHeight - 2);
|
||||
glPopMatrix();
|
||||
setColor(memoryBarColor);
|
||||
drawBox((barWidth - 2) * (usedMemory) / (maxMemory), barHeight - 2);
|
||||
|
||||
// progress text
|
||||
String progress = getMemoryString(usedMemory) + " / " + getMemoryString(maxMemory);
|
||||
glTranslatef(((float)barWidth - 2) / 2 - fontRenderer.getStringWidth(progress), 2, 0);
|
||||
setColor(fontColor);
|
||||
glScalef(2, 2, 1);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
fontRenderer.drawString(progress, 0, 0, 0x000000);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
private String getMemoryString(int memory)
|
||||
{
|
||||
return StringUtils.leftPad(Integer.toString(memory), 4, ' ') + " MB";
|
||||
}
|
||||
|
||||
private void setGL()
|
||||
{
|
||||
lock.lock();
|
||||
try
|
||||
{
|
||||
Display.getDrawable().makeCurrent();
|
||||
}
|
||||
catch (LWJGLException e)
|
||||
{
|
||||
LOGGER.error("Error setting GL context:", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
glClearColor((float)((backgroundColor >> 16) & 0xFF) / 0xFF, (float)((backgroundColor >> 8) & 0xFF) / 0xFF, (float)(backgroundColor & 0xFF) / 0xFF, 1);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
private void clearGL()
|
||||
{
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
mc.displayWidth = Display.getWidth();
|
||||
mc.displayHeight = Display.getHeight();
|
||||
mc.resize(mc.displayWidth, mc.displayHeight);
|
||||
glClearColor(1, 1, 1, 1);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glAlphaFunc(GL_GREATER, .1f);
|
||||
try
|
||||
{
|
||||
Display.getDrawable().releaseContext();
|
||||
}
|
||||
catch (LWJGLException e)
|
||||
{
|
||||
LOGGER.error("Error releasing GL context:", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
});
|
||||
thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler()
|
||||
{
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e)
|
||||
{
|
||||
LOGGER.error("Splash thread Exception", e);
|
||||
threadError = e;
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
checkThreadState();
|
||||
}
|
||||
|
||||
private static int max_texture_size = -1;
|
||||
public static int getMaxTextureSize()
|
||||
{
|
||||
if (max_texture_size != -1) return max_texture_size;
|
||||
for (int i = 0x4000; i > 0; i >>= 1)
|
||||
{
|
||||
GlStateManager.glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, i, i, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);
|
||||
if (GlStateManager.glGetTexLevelParameteri(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH) != 0)
|
||||
{
|
||||
max_texture_size = i;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static void checkThreadState()
|
||||
{
|
||||
if(thread.getState() == Thread.State.TERMINATED || threadError != null)
|
||||
{
|
||||
throw new IllegalStateException("Splash thread", threadError);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Call before you need to explicitly modify GL context state during loading.
|
||||
* Resource loading doesn't usually require this call.
|
||||
* Call {@link #resume()} when you're done.
|
||||
* @deprecated not a stable API, will break, don't use this yet
|
||||
* /
|
||||
@Deprecated
|
||||
public static void pause()
|
||||
{
|
||||
if(!enabled) return;
|
||||
checkThreadState();
|
||||
pause = true;
|
||||
lock.lock();
|
||||
try
|
||||
{
|
||||
d.releaseContext();
|
||||
Display.getDrawable().makeCurrent();
|
||||
}
|
||||
catch (LWJGLException e)
|
||||
{
|
||||
LOGGER.error("Error setting GL context:", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated not a stable API, will break, don't use this yet
|
||||
* /
|
||||
@Deprecated
|
||||
public static void resume()
|
||||
{
|
||||
if(!enabled) return;
|
||||
checkThreadState();
|
||||
pause = false;
|
||||
try
|
||||
{
|
||||
Display.getDrawable().releaseContext();
|
||||
d.makeCurrent();
|
||||
}
|
||||
catch (LWJGLException e)
|
||||
{
|
||||
LOGGER.error("Error releasing GL context:", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
public static void finish()
|
||||
{
|
||||
if(!enabled) return;
|
||||
try
|
||||
{
|
||||
checkThreadState();
|
||||
done = true;
|
||||
thread.join();
|
||||
glFlush(); // process any remaining GL calls before releaseContext (prevents missing textures on mac)
|
||||
d.releaseContext();
|
||||
Display.getDrawable().makeCurrent();
|
||||
fontTexture.delete();
|
||||
logoTexture.delete();
|
||||
forgeTexture.delete();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.error("Error finishing SplashProgress:", e);
|
||||
disableSplash(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean disableSplash(Exception e)
|
||||
{
|
||||
if (disableSplash())
|
||||
{
|
||||
throw new EnhancedRuntimeException(e)
|
||||
{
|
||||
@Override
|
||||
protected void printStackTrace(WrappedPrintStream stream)
|
||||
{
|
||||
stream.println("SplashProgress has detected a error loading Minecraft.");
|
||||
stream.println("This can sometimes be caused by bad video drivers.");
|
||||
stream.println("We have automatically disabled the new Splash Screen in config/splash.properties.");
|
||||
stream.println("Try reloading minecraft before reporting any errors.");
|
||||
}
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new EnhancedRuntimeException(e)
|
||||
{
|
||||
@Override
|
||||
protected void printStackTrace(WrappedPrintStream stream)
|
||||
{
|
||||
stream.println("SplashProgress has detected a error loading Minecraft.");
|
||||
stream.println("This can sometimes be caused by bad video drivers.");
|
||||
stream.println("Please try disabling the new Splash Screen in config/splash.properties.");
|
||||
stream.println("After doing so, try reloading minecraft before reporting any errors.");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean disableSplash()
|
||||
{
|
||||
File configFile = new File(Minecraft.getMinecraft().mcDataDir, "config/splash.properties");
|
||||
File parent = configFile.getParentFile();
|
||||
if (!parent.exists())
|
||||
parent.mkdirs();
|
||||
|
||||
enabled = false;
|
||||
config.setProperty("enabled", "false");
|
||||
|
||||
try (Writer w = new OutputStreamWriter(new FileOutputStream(configFile), StandardCharsets.UTF_8))
|
||||
{
|
||||
config.store(w, "Splash screen properties");
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
LOGGER.error("Could not save the splash.properties file", e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static IResourcePack createResourcePack(File file)
|
||||
{
|
||||
if(file.isDirectory())
|
||||
{
|
||||
return new FolderResourcePack(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new FileResourcePack(file);
|
||||
}
|
||||
}
|
||||
|
||||
private static final IntBuffer buf = BufferUtils.createIntBuffer(4 * 1024 * 1024);
|
||||
|
||||
// From FontRenderer.renderCharAtPos
|
||||
private static final String ALLOWED_CHARS = "\u00c0\u00c1\u00c2\u00c8\u00ca\u00cb\u00cd\u00d3\u00d4\u00d5\u00da\u00df\u00e3\u00f5\u011f\u0130\u0131\u0152\u0153\u015e\u015f\u0174\u0175\u017e\u0207\u0000\u0000\u0000\u0000\u0000\u0000\u0000 !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0000\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u03b2\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u2205\u2208\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u0000";
|
||||
private static final CharMatcher DISALLOWED_CHAR_MATCHER = CharMatcher.anyOf(ALLOWED_CHARS).negate();
|
||||
|
||||
public static String stripSpecialChars(String message)
|
||||
{
|
||||
// We can't handle many unicode points in the splash renderer
|
||||
return DISALLOWED_CHAR_MATCHER.removeFrom(net.minecraft.util.StringUtils.stripControlCodes(message));
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class Texture
|
||||
{
|
||||
private final ResourceLocation location;
|
||||
private final int name;
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final int frames;
|
||||
private final int size;
|
||||
|
||||
public Texture(ResourceLocation location, @Nullable ResourceLocation fallback)
|
||||
{
|
||||
this(location, fallback, true);
|
||||
}
|
||||
|
||||
public Texture(ResourceLocation location, @Nullable ResourceLocation fallback, boolean allowRP)
|
||||
{
|
||||
InputStream s = null;
|
||||
try
|
||||
{
|
||||
this.location = location;
|
||||
s = open(location, fallback, allowRP);
|
||||
ImageInputStream stream = ImageIO.createImageInputStream(s);
|
||||
Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);
|
||||
if(!readers.hasNext()) throw new IOException("No suitable reader found for image" + location);
|
||||
ImageReader reader = readers.next();
|
||||
reader.setInput(stream);
|
||||
int frames = reader.getNumImages(true);
|
||||
BufferedImage[] images = new BufferedImage[frames];
|
||||
for(int i = 0; i < frames; i++)
|
||||
{
|
||||
images[i] = reader.read(i);
|
||||
}
|
||||
reader.dispose();
|
||||
width = images[0].getWidth();
|
||||
int height = images[0].getHeight();
|
||||
// Animation strip
|
||||
if (height > width && height % width == 0)
|
||||
{
|
||||
frames = height / width;
|
||||
BufferedImage original = images[0];
|
||||
height = width;
|
||||
images = new BufferedImage[frames];
|
||||
for (int i = 0; i < frames; i++)
|
||||
{
|
||||
images[i] = original.getSubimage(0, i * height, width, height);
|
||||
}
|
||||
}
|
||||
this.frames = frames;
|
||||
this.height = height;
|
||||
int size = 1;
|
||||
while((size / width) * (size / height) < frames) size *= 2;
|
||||
this.size = size;
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
synchronized(SplashProgress.class)
|
||||
{
|
||||
name = glGenTextures();
|
||||
glBindTexture(GL_TEXTURE_2D, name);
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, (IntBuffer)null);
|
||||
checkGLError("Texture creation");
|
||||
for(int i = 0; i * (size / width) < frames; i++)
|
||||
{
|
||||
for(int j = 0; i * (size / width) + j < frames && j < size / width; j++)
|
||||
{
|
||||
buf.clear();
|
||||
BufferedImage image = images[i * (size / width) + j];
|
||||
for(int k = 0; k < height; k++)
|
||||
{
|
||||
for(int l = 0; l < width; l++)
|
||||
{
|
||||
buf.put(image.getRGB(l, k));
|
||||
}
|
||||
}
|
||||
buf.position(0).limit(width * height);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, j * width, i * height, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buf);
|
||||
checkGLError("Texture uploading");
|
||||
}
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
LOGGER.error("Error reading texture from file: {}", location, e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IOUtils.closeQuietly(s);
|
||||
}
|
||||
}
|
||||
|
||||
public ResourceLocation getLocation()
|
||||
{
|
||||
return location;
|
||||
}
|
||||
|
||||
public int getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
public int getFrames()
|
||||
{
|
||||
return frames;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
public void bind()
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, name);
|
||||
}
|
||||
|
||||
public void delete()
|
||||
{
|
||||
glDeleteTextures(name);
|
||||
}
|
||||
|
||||
public float getU(int frame, float u)
|
||||
{
|
||||
return width * (frame % (size / width) + u) / size;
|
||||
}
|
||||
|
||||
public float getV(int frame, float v)
|
||||
{
|
||||
return height * (frame / (size / width) + v) / size;
|
||||
}
|
||||
|
||||
public void texCoord(int frame, float u, float v)
|
||||
{
|
||||
glTexCoord2f(getU(frame, u), getV(frame, v));
|
||||
}
|
||||
}
|
||||
|
||||
private static class SplashFontRenderer extends FontRenderer
|
||||
{
|
||||
public SplashFontRenderer()
|
||||
{
|
||||
super(Minecraft.getMinecraft().gameSettings, fontTexture.getLocation(), null, false);
|
||||
super.onResourceManagerReload(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindTexture(@Nonnull ResourceLocation location)
|
||||
{
|
||||
if(location != locationFontTexture) throw new IllegalArgumentException();
|
||||
fontTexture.bind();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected IResource getResource(@Nonnull ResourceLocation location) throws IOException
|
||||
{
|
||||
DefaultResourcePack pack = Minecraft.getMinecraft().mcDefaultResourcePack;
|
||||
return new SimpleResource(pack.getPackName(), location, pack.getInputStream(location), null, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawVanillaScreen(TextureManager renderEngine) throws LWJGLException
|
||||
{
|
||||
if(!enabled)
|
||||
{
|
||||
Minecraft.getMinecraft().drawSplashScreen(renderEngine);
|
||||
}
|
||||
}
|
||||
|
||||
public static void clearVanillaResources(TextureManager renderEngine, ResourceLocation mojangLogo)
|
||||
{
|
||||
if(!enabled)
|
||||
{
|
||||
renderEngine.deleteTexture(mojangLogo);
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkGLError(String where)
|
||||
{
|
||||
int err = glGetError();
|
||||
if (err != 0)
|
||||
{
|
||||
throw new IllegalStateException(where + ": " + GLU.gluErrorString(err));
|
||||
}
|
||||
}
|
||||
|
||||
private static InputStream open(ResourceLocation loc, @Nullable ResourceLocation fallback, boolean allowResourcePack) throws IOException
|
||||
{
|
||||
if (!allowResourcePack)
|
||||
return mcPack.getInputStream(loc);
|
||||
|
||||
if(miscPack.resourceExists(loc))
|
||||
{
|
||||
return miscPack.getInputStream(loc);
|
||||
}
|
||||
else if(fmlPack.resourceExists(loc))
|
||||
{
|
||||
return fmlPack.getInputStream(loc);
|
||||
}
|
||||
else if(!mcPack.resourceExists(loc) && fallback != null)
|
||||
{
|
||||
return open(fallback, null, true);
|
||||
}
|
||||
return mcPack.getInputStream(loc);
|
||||
}
|
||||
|
||||
private static int bytesToMb(long bytes)
|
||||
{
|
||||
return (int) (bytes / 1024L / 1024L);
|
||||
}
|
||||
*/
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.common.progress;
|
||||
|
||||
public interface IProgressBarTracker
|
||||
{
|
||||
default void onBarCreated(ProgressBar bar) {}
|
||||
|
||||
default void onStepStarted(ProgressBar bar, int step, String message) {}
|
||||
|
||||
default void onStepFinished(ProgressBar bar, int step, String message) {}
|
||||
|
||||
default void onBarFinished(ProgressBar bar, int step, String message) {}
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.common.progress;
|
||||
|
||||
import net.minecraftforge.fml.common.ClassNameUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Not a fully fleshed out API, may change in future MC versions.
|
||||
* However feel free to use and suggest additions.
|
||||
*/
|
||||
public final class ProgressBar implements AutoCloseable
|
||||
{
|
||||
private final String title;
|
||||
private final int totalSteps;
|
||||
private final Function<String, String> stripChars;
|
||||
private final IProgressBarTracker tracker;
|
||||
private volatile int step = 0;
|
||||
private volatile String message = "";
|
||||
|
||||
public ProgressBar(String title, int totalSteps, Function<String, String> stripChars, IProgressBarTracker tracker)
|
||||
{
|
||||
this.title = title;
|
||||
this.totalSteps = totalSteps;
|
||||
this.stripChars = stripChars;
|
||||
this.tracker = tracker;
|
||||
this.tracker.onBarCreated(this);
|
||||
}
|
||||
|
||||
public void step(Class<?> classToName, String... extra)
|
||||
{
|
||||
step(ClassNameUtils.shortName(classToName) + String.join(" ", extra));
|
||||
}
|
||||
|
||||
public synchronized void step(String newMessage)
|
||||
{
|
||||
if (step > 0)
|
||||
{
|
||||
tracker.onStepFinished(this, step, message);
|
||||
}
|
||||
step++;
|
||||
message = stripChars.apply(newMessage);
|
||||
tracker.onStepStarted(this, step, message);;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current step and message.
|
||||
*/
|
||||
public synchronized Pair<Integer, String> getStepAndMessage()
|
||||
{
|
||||
return Pair.of(step, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total number of steps.
|
||||
*/
|
||||
public int getTotalSteps()
|
||||
{
|
||||
return totalSteps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current title.
|
||||
*/
|
||||
public String getTitle()
|
||||
{
|
||||
return title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close()
|
||||
{
|
||||
if (step > 0)
|
||||
{
|
||||
tracker.onStepFinished(this, step, message);
|
||||
}
|
||||
tracker.onBarFinished(this, step, message);
|
||||
}
|
||||
}
|
|
@ -1,129 +0,0 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.common.progress;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
import net.minecraftforge.fml.client.SplashProgress;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.message.MessageFormatMessage;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import static net.minecraftforge.fml.Logging.SPLASH;
|
||||
|
||||
class StartupProgressBarTracker implements IProgressBarTracker
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final List<ProgressBar> bars = new CopyOnWriteArrayList<>();
|
||||
|
||||
private final boolean timeEachStep;
|
||||
private final int steps;
|
||||
private final Stopwatch stopwatch;
|
||||
@Nullable
|
||||
private Stopwatch stepStopwatch;
|
||||
private String logPrefix = "";
|
||||
|
||||
StartupProgressBarTracker(boolean timeEachStep, int steps)
|
||||
{
|
||||
this.timeEachStep = timeEachStep;
|
||||
this.steps = steps;
|
||||
this.stopwatch = Stopwatch.createUnstarted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBarCreated(ProgressBar bar)
|
||||
{
|
||||
int depth = bars.size();
|
||||
logPrefix = StringUtils.repeat(" ", depth);
|
||||
bars.add(bar);
|
||||
DistExecutor.runWhenOn(Dist.CLIENT, ()-> SplashProgress::processMessages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStepStarted(ProgressBar bar, int step, String message)
|
||||
{
|
||||
if (step == 1)
|
||||
{
|
||||
if (steps > 1)
|
||||
{
|
||||
LOGGER.debug(SPLASH, () -> new MessageFormatMessage("{0}Bar Starting: {1}", logPrefix, bar.getTitle()));
|
||||
if (timeEachStep)
|
||||
{
|
||||
stepStopwatch = Stopwatch.createStarted();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER.debug(SPLASH, () -> new MessageFormatMessage("{0}Bar Starting: {1} - {2}", logPrefix, bar.getTitle(), message));
|
||||
}
|
||||
stopwatch.start();
|
||||
}
|
||||
if (stepStopwatch != null)
|
||||
{
|
||||
LOGGER.debug(SPLASH, () -> new MessageFormatMessage("{0} Bar Step: {1} - {2} - starting", logPrefix, bar.getTitle(), message));
|
||||
stepStopwatch.reset();
|
||||
stepStopwatch.start();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStepFinished(ProgressBar bar, int step, String message)
|
||||
{
|
||||
if (stepStopwatch != null)
|
||||
{
|
||||
stepStopwatch.stop();
|
||||
LOGGER.debug(SPLASH, () -> new MessageFormatMessage("{0} Bar Step: {1} - {2} - took {3}", logPrefix, bar.getTitle(), message, stepStopwatch));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBarFinished(ProgressBar bar, int step, String message)
|
||||
{
|
||||
if (steps > 0)
|
||||
{
|
||||
stopwatch.stop();
|
||||
bars.remove(bar);
|
||||
if (steps > 1)
|
||||
{
|
||||
LOGGER.debug(SPLASH, () -> new MessageFormatMessage("{0}Bar Finished: {1} - took {2}", logPrefix, bar.getTitle(), stopwatch));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER.debug(SPLASH, () -> new MessageFormatMessage("{0}Bar Finished: {1} - {2} - took {3}", logPrefix, bar.getTitle(), message, stopwatch));
|
||||
}
|
||||
DistExecutor.runWhenOn(Dist.CLIENT, () -> SplashProgress::processMessages);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal use only.
|
||||
*/
|
||||
public static Iterator<ProgressBar> barIterator()
|
||||
{
|
||||
return bars.iterator();
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.common.progress;
|
||||
|
||||
import net.minecraftforge.fml.SidedProvider;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class StartupProgressManager
|
||||
{
|
||||
private static final Function<String, String> stripChars = SidedProvider.STRIPCHARS.get();
|
||||
|
||||
public static void start(String title, int steps, Consumer<ProgressBar> task)
|
||||
{
|
||||
start(title, steps, false, task);
|
||||
}
|
||||
|
||||
public static void start(String title, int steps, boolean timeEachStep, Consumer<ProgressBar> task)
|
||||
{
|
||||
try (ProgressBar bar = start(title, steps, timeEachStep))
|
||||
{
|
||||
task.accept(bar);
|
||||
}
|
||||
}
|
||||
|
||||
public static ProgressBar start(String title, int steps)
|
||||
{
|
||||
return start(title, steps, false);
|
||||
}
|
||||
|
||||
public static ProgressBar start(String title, int steps, boolean timeEachStep)
|
||||
{
|
||||
StartupProgressBarTracker tracker = new StartupProgressBarTracker(timeEachStep, steps);
|
||||
return new ProgressBar(title, steps, stripChars, tracker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal use only.
|
||||
*/
|
||||
public static Iterator<ProgressBar> barIterator()
|
||||
{
|
||||
return StartupProgressBarTracker.barIterator();
|
||||
}
|
||||
}
|
|
@ -1,3 +1,22 @@
|
|||
/*
|
||||
* Minecraft Forge
|
||||
* Copyright (c) 2016-2019.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.fml.network;
|
||||
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
|
|
|
@ -42,7 +42,7 @@ public class ServerModLoader
|
|||
SidedProvider.setServer(()->dedicatedServer);
|
||||
LogicalSidedProvider.setServer(()->dedicatedServer);
|
||||
LanguageHook.loadForgeAndMCLangs();
|
||||
ModLoader.get().gatherAndInitializeMods();
|
||||
ModLoader.get().gatherAndInitializeMods(null);
|
||||
ModLoader.get().loadMods(Runnable::run, (a)->{}, (a)->{});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue