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
|
--- a/net/minecraft/client/audio/SoundHandler.java
|
||||||
+++ b/net/minecraft/client/audio/SoundHandler.java
|
+++ b/net/minecraft/client/audio/SoundHandler.java
|
||||||
@@ -61,6 +61,7 @@
|
@@ -210,6 +210,11 @@
|
||||||
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 @@
|
|
||||||
this.field_147694_f.func_195855_a(p_195478_1_, p_195478_2_);
|
this.field_147694_f.func_195855_a(p_195478_1_, p_195478_2_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
--- a/net/minecraft/client/gui/ResourceLoadProgressGui.java
|
--- a/net/minecraft/client/gui/ResourceLoadProgressGui.java
|
||||||
+++ b/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));
|
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_) -> {
|
private static final Comparator<Stitcher.Holder> field_217797_a = Comparator.<Stitcher.Holder, Integer>comparing((p_217793_0_) -> {
|
||||||
return -p_217793_0_.field_94201_d;
|
return -p_217793_0_.field_94201_d;
|
||||||
}).thenComparing((p_217795_0_) -> {
|
}).thenComparing((p_217795_0_) -> {
|
||||||
@@ -50,15 +52,21 @@
|
@@ -53,6 +55,12 @@
|
||||||
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())) {
|
|
||||||
|
|
||||||
for(Stitcher.Holder stitcher$holder : list) {
|
for(Stitcher.Holder stitcher$holder : list) {
|
||||||
+ bar.step(stitcher$holder.field_98151_a.func_195668_m().toString());
|
|
||||||
if (!this.func_94310_b(stitcher$holder)) {
|
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()));
|
+ LOGGER.info(new net.minecraftforge.fml.loading.AdvancedLogMessageAdapter(sb->{
|
||||||
+ for (Stitcher.Holder h : list)
|
+ sb.append("Unable to fit: ").append(stitcher$holder.field_98151_a.func_195668_m());
|
||||||
+ LOGGER.info(" {}", h);
|
+ 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);
|
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 @@
|
@@ -104,7 +112,7 @@
|
||||||
boolean flag4 = flag2 && j != l;
|
boolean flag4 = flag2 && j != l;
|
||||||
boolean flag;
|
boolean flag;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
public boolean func_219533_b(ResourceLocation p_219533_1_) {
|
public boolean func_219533_b(ResourceLocation p_219533_1_) {
|
||||||
IResourceManager iresourcemanager = this.field_199014_c.get(p_219533_1_.func_110624_b());
|
IResourceManager iresourcemanager = this.field_199014_c.get(p_219533_1_.func_110624_b());
|
||||||
return iresourcemanager != null ? iresourcemanager.func_219533_b(p_219533_1_) : false;
|
return iresourcemanager != null ? iresourcemanager.func_219533_b(p_219533_1_) : false;
|
||||||
@@ -118,18 +116,20 @@
|
@@ -118,7 +116,6 @@
|
||||||
return iasyncreloader;
|
return iasyncreloader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,17 +24,3 @@
|
||||||
public IAsyncReloader func_219535_a(Executor p_219535_1_, Executor p_219535_2_, CompletableFuture<Unit> p_219535_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_);
|
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;
|
package net.minecraftforge.fml.loading;
|
||||||
|
|
||||||
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
|
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;
|
package net.minecraftforge.client.model;
|
||||||
|
|
||||||
import net.minecraft.client.renderer.texture.ISprite;
|
import net.minecraft.client.renderer.texture.ISprite;
|
||||||
|
|
|
@ -20,11 +20,7 @@
|
||||||
package net.minecraftforge.common;
|
package net.minecraftforge.common;
|
||||||
|
|
||||||
import net.minecraftforge.eventbus.api.IEventBus;
|
import net.minecraftforge.eventbus.api.IEventBus;
|
||||||
import net.minecraftforge.fml.ExtensionPoint;
|
import net.minecraftforge.fml.*;
|
||||||
import net.minecraftforge.fml.FMLWorldPersistenceHook;
|
|
||||||
import net.minecraftforge.fml.ModLoadingContext;
|
|
||||||
import net.minecraftforge.fml.VersionChecker;
|
|
||||||
import net.minecraftforge.fml.WorldPersistenceHooks;
|
|
||||||
import net.minecraftforge.fml.config.ModConfig;
|
import net.minecraftforge.fml.config.ModConfig;
|
||||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||||
import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent;
|
import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent;
|
||||||
|
@ -103,6 +99,7 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
|
||||||
modEventBus.register(ForgeConfig.class);
|
modEventBus.register(ForgeConfig.class);
|
||||||
// Forge does not display problems when the remote is not matching.
|
// Forge does not display problems when the remote is not matching.
|
||||||
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.DISPLAYTEST, ()-> Pair.of(()->"ANY", (remote, isServer)-> true));
|
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;
|
package net.minecraftforge.common.extensions;
|
||||||
|
|
||||||
import net.minecraft.entity.player.PlayerInventory;
|
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;
|
package net.minecraftforge.common.extensions;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
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;
|
package net.minecraftforge.common.extensions;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
|
@ -41,7 +41,7 @@ public enum LifecycleEventProvider
|
||||||
GATHERDATA(()->new GatherDataLifecycleEvent(ModLoadingStage.GATHERDATA), ModList.inlineDispatcher);
|
GATHERDATA(()->new GatherDataLifecycleEvent(ModLoadingStage.GATHERDATA), ModList.inlineDispatcher);
|
||||||
|
|
||||||
private final Supplier<? extends LifecycleEvent> event;
|
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 Supplier<Event> customEventSupplier;
|
||||||
private LifecycleEvent.Progression progression = LifecycleEvent.Progression.NEXT;
|
private LifecycleEvent.Progression progression = LifecycleEvent.Progression.NEXT;
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ public enum LifecycleEventProvider
|
||||||
this(e, ModList.parallelDispatcher);
|
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.event = e;
|
||||||
this.eventDispatcher = eventDispatcher;
|
this.eventDispatcher = eventDispatcher;
|
||||||
|
@ -64,11 +64,11 @@ public enum LifecycleEventProvider
|
||||||
this.progression = progression;
|
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();
|
final LifecycleEvent lifecycleEvent = this.event.get();
|
||||||
lifecycleEvent.setCustomEventSupplier(this.customEventSupplier);
|
lifecycleEvent.setCustomEventSupplier(this.customEventSupplier);
|
||||||
lifecycleEvent.changeProgression(this.progression);
|
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> {
|
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);
|
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.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
import java.util.concurrent.ForkJoinPool;
|
|
||||||
import java.util.concurrent.ForkJoinWorkerThread;
|
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
@ -81,9 +78,9 @@ public class ModList
|
||||||
return INSTANCE;
|
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() {
|
public static ModList get() {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
|
@ -113,13 +110,17 @@ public class ModList
|
||||||
this.mods.forEach(m->m.transitionState(lifecycleEvent, errorHandler));
|
this.mods.forEach(m->m.transitionState(lifecycleEvent, errorHandler));
|
||||||
FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.consumeLifecycleEvent(()->lifecycleEvent));
|
FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.consumeLifecycleEvent(()->lifecycleEvent));
|
||||||
}
|
}
|
||||||
private void dispatchParallelEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent, final Consumer<List<ModLoadingException>> errorHandler, final Executor executor) {
|
private void dispatchParallelEvent(LifecycleEventProvider.LifecycleEvent lifecycleEvent, final Consumer<List<ModLoadingException>> errorHandler, final Executor executor, final Runnable ticker) {
|
||||||
LOGGER.debug(LOADING, "Dispatching parallel event {}", lifecycleEvent);
|
LOGGER.debug(LOADING, "Dispatching parallel event {}", lifecycleEvent);
|
||||||
FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.consumeLifecycleEvent(()->lifecycleEvent));
|
FMLLoader.getLanguageLoadingProvider().forEach(lp->lp.consumeLifecycleEvent(()->lifecycleEvent));
|
||||||
DeferredWorkQueue.clear();
|
DeferredWorkQueue.clear();
|
||||||
try
|
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)
|
catch (InterruptedException | ExecutionException e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -102,7 +102,7 @@ public class ModLoader
|
||||||
private final List<ModLoadingWarning> loadingWarnings;
|
private final List<ModLoadingWarning> loadingWarnings;
|
||||||
private GatherDataEvent.DataGeneratorConfig dataGeneratorConfig;
|
private GatherDataEvent.DataGeneratorConfig dataGeneratorConfig;
|
||||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||||
private Optional<Consumer<String>> statusConsumer = Optional.empty();
|
private final Optional<Consumer<String>> statusConsumer = StartupMessageManager.modLoaderConsumer();
|
||||||
|
|
||||||
private ModLoader()
|
private ModLoader()
|
||||||
{
|
{
|
||||||
|
@ -127,15 +127,15 @@ public class ModLoader
|
||||||
DistExecutor.runWhenOn(Dist.CLIENT, ()->()-> ConfigTracker.INSTANCE.loadConfigs(ModConfig.Type.CLIENT, FMLPaths.CONFIGDIR.get()));
|
DistExecutor.runWhenOn(Dist.CLIENT, ()->()-> ConfigTracker.INSTANCE.loadConfigs(ModConfig.Type.CLIENT, FMLPaths.CONFIGDIR.get()));
|
||||||
ConfigTracker.INSTANCE.loadConfigs(ModConfig.Type.COMMON, FMLPaths.CONFIGDIR.get());
|
ConfigTracker.INSTANCE.loadConfigs(ModConfig.Type.COMMON, FMLPaths.CONFIGDIR.get());
|
||||||
statusConsumer.ifPresent(c->c.accept("Mod setup: SETUP"));
|
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"));
|
statusConsumer.ifPresent(c->c.accept("Mod setup: SIDED SETUP"));
|
||||||
mainThreadExecutor.execute(()->preSidedRunnable.accept(c->ModList.get().forEachModContainer((mi,mc)->mc.acceptEvent(c.get()))));
|
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()))));
|
mainThreadExecutor.execute(()->postSidedRunnable.accept(c->ModList.get().forEachModContainer((mi,mc)->mc.acceptEvent(c.get()))));
|
||||||
statusConsumer.ifPresent(c->c.accept("Mod setup complete"));
|
statusConsumer.ifPresent(c->c.accept("Mod setup complete"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void gatherAndInitializeMods() {
|
public void gatherAndInitializeMods(final Runnable ticker) {
|
||||||
statusConsumer.ifPresent(c->c.accept("Loading mods"));
|
statusConsumer.ifPresent(c->c.accept("Loading mods"));
|
||||||
final ModList modList = ModList.of(loadingModList.getModFiles().stream().map(ModFileInfo::getFile).collect(Collectors.toList()), loadingModList.getMods());
|
final ModList modList = ModList.of(loadingModList.getModFiles().stream().map(ModFileInfo::getFile).collect(Collectors.toList()), loadingModList.getMods());
|
||||||
if (!this.loadingExceptions.isEmpty()) {
|
if (!this.loadingExceptions.isEmpty()) {
|
||||||
|
@ -155,22 +155,22 @@ public class ModLoader
|
||||||
throw new LoadingFailedException(loadingExceptions);
|
throw new LoadingFailedException(loadingExceptions);
|
||||||
}
|
}
|
||||||
modList.setLoadedMods(modContainers);
|
modList.setLoadedMods(modContainers);
|
||||||
statusConsumer.ifPresent(c->c.accept("Constructing mods"));
|
statusConsumer.ifPresent(c->c.accept(String.format("Constructing %d mods", modList.size())));
|
||||||
dispatchAndHandleError(LifecycleEventProvider.CONSTRUCT, Runnable::run);
|
dispatchAndHandleError(LifecycleEventProvider.CONSTRUCT, Runnable::run, ticker);
|
||||||
statusConsumer.ifPresent(c->c.accept("Creating registries"));
|
statusConsumer.ifPresent(c->c.accept("Creating registries"));
|
||||||
GameData.fireCreateRegistryEvents(LifecycleEventProvider.CREATE_REGISTRIES, event -> dispatchAndHandleError(event, Runnable::run));
|
GameData.fireCreateRegistryEvents(LifecycleEventProvider.CREATE_REGISTRIES, event -> dispatchAndHandleError(event, Runnable::run, ticker));
|
||||||
ObjectHolderRegistry.findObjectHolders();
|
ObjectHolderRegistry.findObjectHolders();
|
||||||
CapabilityManager.INSTANCE.injectCapabilities(modList.getAllScanData());
|
CapabilityManager.INSTANCE.injectCapabilities(modList.getAllScanData());
|
||||||
statusConsumer.ifPresent(c->c.accept("Populating registries"));
|
statusConsumer.ifPresent(c->c.accept("Populating registries"));
|
||||||
GameData.fireRegistryEvents(rl->true, LifecycleEventProvider.LOAD_REGISTRIES, event -> dispatchAndHandleError(event, Runnable::run));
|
GameData.fireRegistryEvents(rl->true, LifecycleEventProvider.LOAD_REGISTRIES, event -> dispatchAndHandleError(event, Runnable::run, ticker));
|
||||||
statusConsumer.ifPresent(c->c.accept("Early mod loading complete"));
|
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()) {
|
if (!loadingExceptions.isEmpty()) {
|
||||||
LOGGER.error(LOADING,"Skipping lifecycle event {}, {} errors found.", event, loadingExceptions.size());
|
LOGGER.error(LOADING,"Skipping lifecycle event {}, {} errors found.", event, loadingExceptions.size());
|
||||||
} else {
|
} else {
|
||||||
event.dispatch(this::accumulateErrors, executor);
|
event.dispatch(this::accumulateErrors, executor, ticker);
|
||||||
}
|
}
|
||||||
if (!loadingExceptions.isEmpty()) {
|
if (!loadingExceptions.isEmpty()) {
|
||||||
LOGGER.fatal(LOADING,"Failed to complete lifecycle event {}, {} errors found", event, loadingExceptions.size());
|
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)
|
public void finishMods(Executor mainThreadExecutor)
|
||||||
{
|
{
|
||||||
statusConsumer.ifPresent(c->c.accept("Mod setup: ENQUEUE IMC"));
|
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"));
|
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"));
|
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"));
|
statusConsumer.ifPresent(c->c.accept("Freezing data"));
|
||||||
GameData.freezeData();
|
GameData.freezeData();
|
||||||
NetworkRegistry.lock();
|
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()
|
public List<ModLoadingWarning> getWarnings()
|
||||||
|
@ -246,16 +246,12 @@ public class ModLoader
|
||||||
LOGGER.info("Initializing Data Gatherer for mods {}", mods);
|
LOGGER.info("Initializing Data Gatherer for mods {}", mods);
|
||||||
Bootstrap.register();
|
Bootstrap.register();
|
||||||
dataGeneratorConfig = new GatherDataEvent.DataGeneratorConfig(mods, path, inputs, serverGenerators, clientGenerators, devToolGenerators, reportsGenerator, structureValidator);
|
dataGeneratorConfig = new GatherDataEvent.DataGeneratorConfig(mods, path, inputs, serverGenerators, clientGenerators, devToolGenerators, reportsGenerator, structureValidator);
|
||||||
gatherAndInitializeMods();
|
gatherAndInitializeMods(null);
|
||||||
dispatchAndHandleError(LifecycleEventProvider.GATHERDATA, Runnable::run);
|
dispatchAndHandleError(LifecycleEventProvider.GATHERDATA, Runnable::run, null);
|
||||||
dataGeneratorConfig.runAll();
|
dataGeneratorConfig.runAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Function<ModContainer, ModLifecycleEvent> getDataGeneratorEvent() {
|
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);
|
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);
|
SidedProvider.setClient(()->minecraft);
|
||||||
LogicalSidedProvider.setClient(()->minecraft);
|
LogicalSidedProvider.setClient(()->minecraft);
|
||||||
earlyLoaderGUI = new EarlyLoaderGUI(minecraft.mainWindow);
|
earlyLoaderGUI = new EarlyLoaderGUI(minecraft.mainWindow);
|
||||||
ModLoader.get().setStatusConsumer(earlyLoaderGUI.getStatusConsumer());
|
createRunnableWithCatch(() -> ModLoader.get().gatherAndInitializeMods(earlyLoaderGUI::renderTick)).run();
|
||||||
createRunnableWithCatch(ModLoader.get()::gatherAndInitializeMods).run();
|
|
||||||
ResourcePackLoader.loadResourcePacks(defaultResourcePacks);
|
ResourcePackLoader.loadResourcePacks(defaultResourcePacks);
|
||||||
mcResourceManager.addReloadListener(ClientModLoader::onreload);
|
mcResourceManager.addReloadListener(ClientModLoader::onreload);
|
||||||
mcResourceManager.addReloadListener(BrandingControl.resourceManagerReloadListener());
|
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;
|
package net.minecraftforge.fml.client;
|
||||||
|
|
||||||
|
import com.google.common.base.Ascii;
|
||||||
|
import com.google.common.base.CharMatcher;
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
import net.minecraft.client.MainWindow;
|
import net.minecraft.client.MainWindow;
|
||||||
import net.minecraft.client.Minecraft;
|
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.GL11;
|
||||||
|
import org.lwjgl.opengl.GL14;
|
||||||
import org.lwjgl.stb.STBEasyFont;
|
import org.lwjgl.stb.STBEasyFont;
|
||||||
|
import org.lwjgl.stb.STBImage;
|
||||||
import org.lwjgl.system.MemoryUtil;
|
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.nio.ByteBuffer;
|
||||||
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class EarlyLoaderGUI {
|
public class EarlyLoaderGUI {
|
||||||
private final MainWindow window;
|
private final MainWindow window;
|
||||||
private String message;
|
|
||||||
private boolean handledElsewhere;
|
private boolean handledElsewhere;
|
||||||
|
|
||||||
public EarlyLoaderGUI(final MainWindow window) {
|
public EarlyLoaderGUI(final MainWindow window) {
|
||||||
|
@ -22,51 +52,69 @@ public class EarlyLoaderGUI {
|
||||||
window.update(false);
|
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() {
|
public void handleElsewhere() {
|
||||||
this.handledElsewhere = true;
|
this.handledElsewhere = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderFromGUI() {
|
void renderFromGUI() {
|
||||||
doMatrix();
|
renderMessages();
|
||||||
renderMessage();
|
|
||||||
}
|
}
|
||||||
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);
|
GlStateManager.enableClientState(GL11.GL_VERTEX_ARRAY);
|
||||||
ByteBuffer charBuffer = MemoryUtil.memAlloc(this.message.length() * 270);
|
ByteBuffer charBuffer = MemoryUtil.memAlloc(message.length() * 270);
|
||||||
int quads = STBEasyFont.stb_easy_font_print(0, 0, this.message, null, charBuffer);
|
int quads = STBEasyFont.stb_easy_font_print(0, 0, message, null, charBuffer);
|
||||||
GlStateManager.vertexPointer(2, GL11.GL_FLOAT, 16, 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.pushMatrix();
|
||||||
GlStateManager.translatef(10, window.getFramebufferHeight() - 50, 0);
|
GlStateManager.translatef(10, window.getScaledHeight() - 15 - line * 10, 0);
|
||||||
GlStateManager.scalef(3, 3, 0);
|
GlStateManager.scalef(1, 1, 0);
|
||||||
GlStateManager.drawArrays(GL11.GL_QUADS, 0, quads * 4);
|
GlStateManager.drawArrays(GL11.GL_QUADS, 0, quads * 4);
|
||||||
GlStateManager.popMatrix();
|
GlStateManager.popMatrix();
|
||||||
|
|
||||||
MemoryUtil.memFree(charBuffer);
|
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;
|
package net.minecraftforge.fml.network;
|
||||||
|
|
||||||
import net.minecraft.entity.player.PlayerInventory;
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class ServerModLoader
|
||||||
SidedProvider.setServer(()->dedicatedServer);
|
SidedProvider.setServer(()->dedicatedServer);
|
||||||
LogicalSidedProvider.setServer(()->dedicatedServer);
|
LogicalSidedProvider.setServer(()->dedicatedServer);
|
||||||
LanguageHook.loadForgeAndMCLangs();
|
LanguageHook.loadForgeAndMCLangs();
|
||||||
ModLoader.get().gatherAndInitializeMods();
|
ModLoader.get().gatherAndInitializeMods(null);
|
||||||
ModLoader.get().loadMods(Runnable::run, (a)->{}, (a)->{});
|
ModLoader.get().loadMods(Runnable::run, (a)->{}, (a)->{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue