Add a super early GUI for showing pre-game launch messages from FML. NOTE: this cannot show on MAC because MAC can't handle
off-thread GUIs in any way shape or form, and we need the main thread to do real work. Fix forge fading in wrongly. Signed-off-by: cpw <cpw+github@weeksfamily.ca>
This commit is contained in:
parent
b294f4d894
commit
9c759294c6
18 changed files with 512 additions and 124 deletions
|
@ -402,7 +402,7 @@ project(':forge') {
|
|||
installer 'cpw.mods:grossjava9hacks:1.1.+'
|
||||
installer 'net.minecraftforge:accesstransformers:1.0.+:shadowed'
|
||||
installer 'net.minecraftforge:eventbus:1.0.+:service'
|
||||
installer 'net.minecraftforge:forgespi:1.3.+'
|
||||
installer 'net.minecraftforge:forgespi:1.4.+'
|
||||
installer 'net.minecraftforge:coremods:1.0.+'
|
||||
installer 'net.minecraftforge:unsafe:0.2.+'
|
||||
installer 'com.electronwill.night-config:core:3.6.0'
|
||||
|
@ -417,6 +417,10 @@ project(':forge') {
|
|||
installer 'net.sf.jopt-simple:jopt-simple:5.0.4'
|
||||
fmllauncherImplementation 'com.google.guava:guava:21.0'
|
||||
fmllauncherImplementation 'com.google.code.gson:gson:2.8.0'
|
||||
fmllauncherImplementation "org.lwjgl:lwjgl:3.2.2"
|
||||
fmllauncherImplementation "org.lwjgl:lwjgl-glfw:3.2.2"
|
||||
fmllauncherImplementation "org.lwjgl:lwjgl-opengl:3.2.2"
|
||||
fmllauncherImplementation "org.lwjgl:lwjgl-stb:3.2.2"
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.0.0'
|
||||
testImplementation 'org.junit.vintage:junit-vintage-engine:5.+'
|
||||
testImplementation 'org.opentest4j:opentest4j:1.0.0' // needed for junit 5
|
||||
|
|
|
@ -25,7 +25,15 @@
|
|||
this.field_71459_aj = p_i45547_1_.field_178741_d.field_178756_a;
|
||||
this.field_147129_ai = func_147122_X();
|
||||
this.field_71437_Z = null;
|
||||
@@ -442,7 +442,6 @@
|
||||
@@ -423,6 +423,7 @@
|
||||
screensize = new ScreenSize(this.field_71474_y.field_92118_B, this.field_71474_y.field_92119_C, screensize.field_216496_c, screensize.field_216497_d, screensize.field_216498_e);
|
||||
}
|
||||
|
||||
+ net.minecraftforge.fml.loading.progress.EarlyProgressVisualization.INSTANCE.join();
|
||||
LongSupplier longsupplier = GLX.initGlfw();
|
||||
if (longsupplier != null) {
|
||||
Util.field_211180_a = longsupplier;
|
||||
@@ -442,7 +443,6 @@
|
||||
|
||||
this.field_195558_d.func_216526_a(this.field_71474_y.field_74350_i);
|
||||
this.field_71417_B = new MouseHelper(this);
|
||||
|
@ -33,7 +41,7 @@
|
|||
this.field_195559_v = new KeyboardListener(this);
|
||||
this.field_195559_v.func_197968_a(this.field_195558_d.func_198092_i());
|
||||
GLX.init();
|
||||
@@ -451,6 +450,7 @@
|
||||
@@ -451,6 +451,7 @@
|
||||
this.field_147124_at.func_147604_a(0.0F, 0.0F, 0.0F, 0.0F);
|
||||
this.field_110451_am = new SimpleReloadableResourceManager(ResourcePackType.CLIENT_RESOURCES, this.field_152352_aC);
|
||||
this.field_71474_y.func_198017_a(this.field_110448_aq);
|
||||
|
@ -41,7 +49,7 @@
|
|||
this.field_110448_aq.func_198983_a();
|
||||
List<IResourcePack> list = this.field_110448_aq.func_198980_d().stream().map(ResourcePackInfo::func_195796_e).collect(Collectors.toList());
|
||||
|
||||
@@ -516,12 +516,14 @@
|
||||
@@ -516,12 +517,14 @@
|
||||
this.field_110451_am.func_219534_a(this.field_193995_ae);
|
||||
GlStateManager.viewport(0, 0, this.field_195558_d.func_198109_k(), this.field_195558_d.func_198091_l());
|
||||
this.field_71452_i = new ParticleManager(this.field_71441_e, this.field_71446_o);
|
||||
|
@ -57,7 +65,7 @@
|
|||
this.field_184132_p = new DebugRenderer(this);
|
||||
GLX.setGlfwErrorCallback(this::func_195545_a);
|
||||
if (this.field_71474_y.field_74353_u && !this.field_195558_d.func_198113_j()) {
|
||||
@@ -532,18 +534,20 @@
|
||||
@@ -532,18 +535,20 @@
|
||||
this.field_195558_d.func_216523_b(this.field_71474_y.field_74352_v);
|
||||
this.field_195558_d.func_224798_d(this.field_71474_y.field_225307_E);
|
||||
this.field_195558_d.func_198112_b();
|
||||
|
@ -84,7 +92,7 @@
|
|||
}, false));
|
||||
}
|
||||
|
||||
@@ -558,7 +562,7 @@
|
||||
@@ -558,7 +563,7 @@
|
||||
return Stream.of(Registry.field_212630_s.func_177774_c(p_213251_0_.func_77973_b()));
|
||||
});
|
||||
SearchTreeReloadable<ItemStack> searchtreereloadable = new SearchTreeReloadable<>((p_213235_0_) -> {
|
||||
|
@ -93,7 +101,7 @@
|
|||
});
|
||||
NonNullList<ItemStack> nonnulllist = NonNullList.func_191196_a();
|
||||
|
||||
@@ -647,7 +651,7 @@
|
||||
@@ -647,7 +652,7 @@
|
||||
Bootstrap.func_179870_a(p_71377_1_.func_71502_e());
|
||||
if (p_71377_1_.func_71497_f() != null) {
|
||||
Bootstrap.func_179870_a("#@!@# Game crashed! Crash report saved to: #@!@# " + p_71377_1_.func_71497_f());
|
||||
|
@ -102,7 +110,7 @@
|
|||
} else if (p_71377_1_.func_147149_a(file2)) {
|
||||
Bootstrap.func_179870_a("#@!@# Game crashed! Crash report saved to: #@!@# " + file2.getAbsolutePath());
|
||||
System.exit(-1);
|
||||
@@ -662,6 +666,7 @@
|
||||
@@ -662,6 +667,7 @@
|
||||
return this.field_71474_y.field_211842_aO;
|
||||
}
|
||||
|
||||
|
@ -110,7 +118,7 @@
|
|||
public CompletableFuture<Void> func_213237_g() {
|
||||
if (this.field_213276_aV != null) {
|
||||
return this.field_213276_aV;
|
||||
@@ -741,16 +746,20 @@
|
||||
@@ -741,16 +747,20 @@
|
||||
}
|
||||
|
||||
public void func_147108_a(@Nullable Screen p_147108_1_) {
|
||||
|
@ -135,7 +143,7 @@
|
|||
if (p_147108_1_ instanceof MainMenuScreen || p_147108_1_ instanceof MultiplayerScreen) {
|
||||
this.field_71474_y.field_74330_P = false;
|
||||
this.field_71456_v.func_146158_b().func_146231_a(true);
|
||||
@@ -875,11 +884,13 @@
|
||||
@@ -875,11 +885,13 @@
|
||||
GlStateManager.enableTexture();
|
||||
this.field_71424_I.func_76319_b();
|
||||
if (!this.field_71454_w) {
|
||||
|
@ -149,7 +157,7 @@
|
|||
}
|
||||
|
||||
this.field_71424_I.func_219897_b();
|
||||
@@ -1147,10 +1158,10 @@
|
||||
@@ -1147,10 +1159,10 @@
|
||||
if (p_147115_1_ && this.field_71476_x != null && this.field_71476_x.func_216346_c() == RayTraceResult.Type.BLOCK) {
|
||||
BlockRayTraceResult blockraytraceresult = (BlockRayTraceResult)this.field_71476_x;
|
||||
BlockPos blockpos = blockraytraceresult.func_216350_a();
|
||||
|
@ -162,7 +170,7 @@
|
|||
this.field_71439_g.func_184609_a(Hand.MAIN_HAND);
|
||||
}
|
||||
}
|
||||
@@ -1177,7 +1188,7 @@
|
||||
@@ -1177,7 +1189,7 @@
|
||||
case BLOCK:
|
||||
BlockRayTraceResult blockraytraceresult = (BlockRayTraceResult)this.field_71476_x;
|
||||
BlockPos blockpos = blockraytraceresult.func_216350_a();
|
||||
|
@ -171,7 +179,7 @@
|
|||
this.field_71442_b.func_180511_b(blockpos, blockraytraceresult.func_216354_b());
|
||||
break;
|
||||
}
|
||||
@@ -1187,6 +1198,7 @@
|
||||
@@ -1187,6 +1199,7 @@
|
||||
}
|
||||
|
||||
this.field_71439_g.func_184821_cY();
|
||||
|
@ -179,7 +187,7 @@
|
|||
}
|
||||
|
||||
this.field_71439_g.func_184609_a(Hand.MAIN_HAND);
|
||||
@@ -1236,6 +1248,9 @@
|
||||
@@ -1236,6 +1249,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,7 +197,7 @@
|
|||
if (!itemstack.func_190926_b() && this.field_71442_b.func_187101_a(this.field_71439_g, this.field_71441_e, hand) == ActionResultType.SUCCESS) {
|
||||
this.field_71460_t.field_78516_c.func_187460_a(hand);
|
||||
return;
|
||||
@@ -1255,6 +1270,8 @@
|
||||
@@ -1255,6 +1271,8 @@
|
||||
--this.field_71467_ac;
|
||||
}
|
||||
|
||||
|
@ -198,7 +206,7 @@
|
|||
this.field_71424_I.func_76320_a("gui");
|
||||
if (!this.field_71445_n) {
|
||||
this.field_71456_v.func_73831_a();
|
||||
@@ -1373,6 +1390,8 @@
|
||||
@@ -1373,6 +1391,8 @@
|
||||
this.field_71424_I.func_219895_b("keyboard");
|
||||
this.field_195559_v.func_204870_b();
|
||||
this.field_71424_I.func_76319_b();
|
||||
|
@ -207,7 +215,7 @@
|
|||
}
|
||||
|
||||
private void func_184117_aA() {
|
||||
@@ -1527,6 +1546,12 @@
|
||||
@@ -1527,6 +1547,12 @@
|
||||
this.func_147108_a(worldloadprogressscreen);
|
||||
|
||||
while(!this.field_71437_Z.func_71200_ad()) {
|
||||
|
@ -220,7 +228,7 @@
|
|||
worldloadprogressscreen.tick();
|
||||
this.func_195542_b(false);
|
||||
|
||||
@@ -1547,11 +1572,17 @@
|
||||
@@ -1547,11 +1573,17 @@
|
||||
networkmanager.func_150719_a(new ClientLoginNetHandler(networkmanager, this, (Screen)null, (p_213261_0_) -> {
|
||||
}));
|
||||
networkmanager.func_179290_a(new CHandshakePacket(socketaddress.toString(), 0, ProtocolType.LOGIN));
|
||||
|
@ -239,7 +247,7 @@
|
|||
WorkingScreen workingscreen = new WorkingScreen();
|
||||
workingscreen.func_200210_a(new TranslationTextComponent("connect.joining"));
|
||||
this.func_213241_c(workingscreen);
|
||||
@@ -1583,10 +1614,12 @@
|
||||
@@ -1583,10 +1615,12 @@
|
||||
IntegratedServer integratedserver = this.field_71437_Z;
|
||||
this.field_71437_Z = null;
|
||||
this.field_71460_t.func_190564_k();
|
||||
|
@ -252,7 +260,7 @@
|
|||
if (integratedserver != null) {
|
||||
while(!integratedserver.func_213201_w()) {
|
||||
this.func_195542_b(false);
|
||||
@@ -1624,6 +1657,7 @@
|
||||
@@ -1624,6 +1658,7 @@
|
||||
}
|
||||
|
||||
TileEntityRendererDispatcher.field_147556_a.func_147543_a(p_213257_1_);
|
||||
|
@ -260,7 +268,7 @@
|
|||
}
|
||||
|
||||
public final boolean func_71355_q() {
|
||||
@@ -1649,112 +1683,8 @@
|
||||
@@ -1649,112 +1684,8 @@
|
||||
|
||||
private void func_147112_ai() {
|
||||
if (this.field_71476_x != null && this.field_71476_x.func_216346_c() != RayTraceResult.Type.MISS) {
|
||||
|
@ -375,7 +383,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
@@ -1826,6 +1756,7 @@
|
||||
@@ -1826,6 +1757,7 @@
|
||||
return field_71432_P;
|
||||
}
|
||||
|
||||
|
@ -383,7 +391,7 @@
|
|||
public CompletableFuture<Void> func_213245_w() {
|
||||
return this.func_213169_a(this::func_213237_g).thenCompose((p_213240_0_) -> {
|
||||
return p_213240_0_;
|
||||
@@ -1972,6 +1903,8 @@
|
||||
@@ -1972,6 +1904,8 @@
|
||||
}
|
||||
|
||||
public MusicTicker.MusicType func_147109_W() {
|
||||
|
@ -392,7 +400,7 @@
|
|||
if (this.field_71462_r instanceof WinGameScreen) {
|
||||
return MusicTicker.MusicType.CREDITS;
|
||||
} else if (this.field_71439_g == null) {
|
||||
@@ -2128,4 +2061,12 @@
|
||||
@@ -2128,4 +2062,12 @@
|
||||
public LoadingGui func_213250_au() {
|
||||
return this.field_213279_p;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
if (this.field_73975_c != null) {
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translatef((float)(this.width / 2 + 90), 70.0F, 0.0F);
|
||||
@@ -222,7 +229,10 @@
|
||||
@@ -222,7 +229,13 @@
|
||||
s = s + ("release".equalsIgnoreCase(this.minecraft.func_184123_d()) ? "" : "/" + this.minecraft.func_184123_d());
|
||||
}
|
||||
|
||||
|
@ -57,10 +57,13 @@
|
|||
+ this.drawString(this.font, brd, 2, this.height - ( 10 + brdline * (this.font.field_78288_b + 1)), 16777215 | l)
|
||||
+ );
|
||||
+
|
||||
+ net.minecraftforge.fml.BrandingControl.forEachAboveCopyrightLine((brdline, brd) ->
|
||||
+ this.drawString(this.font, brd, this.width - font.func_78256_a(brd), this.height - (10 + (brdline + 1) * ( this.font.field_78288_b + 1)), 16777215 | l)
|
||||
+ );
|
||||
this.drawString(this.font, "Copyright Mojang AB. Do not distribute!", this.field_193979_N, this.height - 10, 16777215 | l);
|
||||
if (p_render_1_ > this.field_193979_N && p_render_1_ < this.field_193979_N + this.field_193978_M && p_render_2_ > this.height - 10 && p_render_2_ < this.height) {
|
||||
fill(this.field_193979_N, this.height - 1, this.field_193979_N + this.field_193978_M, this.height, 16777215 | l);
|
||||
@@ -240,6 +250,7 @@
|
||||
@@ -240,6 +253,7 @@
|
||||
if (this.func_183501_a() && f1 >= 1.0F) {
|
||||
this.field_183503_M.render(p_render_1_, p_render_2_, p_render_3_);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/net/minecraft/item/DyeColor.java
|
||||
+++ b/net/minecraft/item/DyeColor.java
|
||||
@@ -43,6 +43,7 @@
|
||||
@@ -41,6 +41,7 @@
|
||||
private final int field_196066_w;
|
||||
private final float[] field_193352_x;
|
||||
private final int field_196067_y;
|
||||
|
@ -8,7 +8,7 @@
|
|||
private final int field_218390_z;
|
||||
|
||||
private DyeColor(int p_i50049_3_, String p_i50049_4_, int p_i50049_5_, MaterialColor p_i50049_6_, int p_i50049_7_, int p_i50049_8_) {
|
||||
@@ -55,6 +56,7 @@
|
||||
@@ -53,6 +54,7 @@
|
||||
int j = (p_i50049_5_ & '\uff00') >> 8;
|
||||
int k = (p_i50049_5_ & 255) >> 0;
|
||||
this.field_196066_w = k << 16 | j << 8 | i << 0;
|
||||
|
@ -16,7 +16,7 @@
|
|||
this.field_193352_x = new float[]{(float)i / 255.0F, (float)j / 255.0F, (float)k / 255.0F};
|
||||
this.field_196067_y = p_i50049_7_;
|
||||
}
|
||||
@@ -120,4 +122,25 @@
|
||||
@@ -115,4 +117,25 @@
|
||||
public String func_176610_l() {
|
||||
return this.field_176785_v;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ import net.minecraftforge.api.distmarker.Dist;
|
|||
import net.minecraftforge.fml.loading.moddiscovery.BackgroundScanHandler;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModDiscoverer;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||
import net.minecraftforge.fml.loading.progress.EarlyProgressVisualization;
|
||||
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
|
||||
import net.minecraftforge.forgespi.Environment;
|
||||
import net.minecraftforge.forgespi.coremod.ICoreModProvider;
|
||||
import net.minecraftforge.forgespi.locating.IModFile;
|
||||
|
@ -176,6 +178,8 @@ public class FMLLoader
|
|||
FMLCommonLaunchHandler commonLaunchHandler = (FMLCommonLaunchHandler)launchHandler.get();
|
||||
naming = commonLaunchHandler.getNaming();
|
||||
dist = commonLaunchHandler.getDist();
|
||||
EarlyProgressVisualization.INSTANCE.accept(dist);
|
||||
StartupMessageManager.modLoaderConsumer().ifPresent(c->c.accept("Early Loading!"));
|
||||
accessTransformer.getExtension().accept(Pair.of(naming, "srg"));
|
||||
|
||||
mcVersion = (String) arguments.get("mcVersion");
|
||||
|
@ -232,13 +236,12 @@ public class FMLLoader
|
|||
public static void beforeStart(ITransformingClassLoader launchClassLoader)
|
||||
{
|
||||
FMLLoader.launchClassLoader = (TransformingClassLoader) launchClassLoader.getInstance();
|
||||
StartupMessageManager.modLoaderConsumer().ifPresent(c->c.accept("Launching minecraft"));
|
||||
}
|
||||
|
||||
|
||||
public static LoadingModList getLoadingModList()
|
||||
{
|
||||
return loadingModList;
|
||||
|
||||
}
|
||||
|
||||
public static TransformingClassLoader getLaunchClassLoader()
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package net.minecraftforge.fml.loading;
|
||||
|
||||
import cpw.mods.modlauncher.ServiceLoaderStreamUtils;
|
||||
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
|
||||
import net.minecraftforge.forgespi.language.IModLanguageProvider;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ExplodedDirectoryLocator;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||
|
@ -127,6 +128,7 @@ public class LanguageLoadingProvider
|
|||
throw new RuntimeException("Failed to find implementation version for language provider "+ lp.name());
|
||||
}
|
||||
LOGGER.debug(CORE, "Found language provider {}, version {}", lp.name(), impl);
|
||||
StartupMessageManager.modLoaderConsumer().ifPresent(c->c.accept("Loaded language provider "+lp.name()+ " " + impl));
|
||||
languageProviderMap.put(lp.name(), new ModLanguageWrapper(lp, new DefaultArtifactVersion(impl)));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import cpw.mods.modlauncher.ServiceLoaderStreamUtils;
|
|||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import net.minecraftforge.fml.loading.LoadingModList;
|
||||
import net.minecraftforge.fml.loading.ModSorter;
|
||||
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
|
||||
import net.minecraftforge.forgespi.Environment;
|
||||
import net.minecraftforge.forgespi.locating.IModFile;
|
||||
import net.minecraftforge.forgespi.locating.IModLocator;
|
||||
|
@ -66,6 +67,7 @@ public class ModDiscoverer {
|
|||
|
||||
public ModDiscoverer(Map<String, ?> arguments) {
|
||||
Launcher.INSTANCE.environment().computePropertyIfAbsent(Environment.Keys.MODFOLDERFACTORY.get(), v->ModsFolderLocator::new);
|
||||
Launcher.INSTANCE.environment().computePropertyIfAbsent(Environment.Keys.PROGRESSMESSAGE.get(), v->StartupMessageManager.locatorConsumer().orElseGet(()->s->{}));
|
||||
locators = ServiceLoader.load(IModLocator.class);
|
||||
locatorList = ServiceLoaderStreamUtils.toList(this.locators);
|
||||
locatorList.forEach(l->l.initArguments(arguments));
|
||||
|
@ -85,6 +87,7 @@ public class ModDiscoverer {
|
|||
.map(IModLocator::scanMods)
|
||||
.flatMap(Collection::stream)
|
||||
.peek(mf -> LOGGER.debug(SCAN,"Found mod file {} of type {} with locator {}", mf.getFileName(), mf.getType(), mf.getLocator()))
|
||||
.peek(mf -> StartupMessageManager.modLoaderConsumer().ifPresent(c->c.accept("Found mod file "+mf.getFileName()+" of type "+mf.getType())))
|
||||
.map(ModFile.class::cast)
|
||||
.collect(Collectors.groupingBy(IModFile::getType));
|
||||
|
||||
|
@ -102,6 +105,7 @@ public class ModDiscoverer {
|
|||
}
|
||||
}
|
||||
LOGGER.debug(SCAN,"Found {} mod files with {} mods", mods::size, ()->mods.stream().mapToInt(mf -> mf.getModInfos().size()).sum());
|
||||
StartupMessageManager.modLoaderConsumer().ifPresent(c->c.accept("Found "+mods.size()+" modfiles to load"));
|
||||
final LoadingModList loadingModList = ModSorter.sort(mods);
|
||||
loadingModList.addCoreMods();
|
||||
loadingModList.addAccessTransformers();
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package net.minecraftforge.fml.loading.moddiscovery;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
|
||||
import net.minecraftforge.forgespi.language.IModFileInfo;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
import net.minecraftforge.forgespi.language.ModFileScanData;
|
||||
|
@ -178,6 +179,7 @@ public class ModFile implements IModFile {
|
|||
if (throwable != null) {
|
||||
this.scanError = throwable;
|
||||
}
|
||||
StartupMessageManager.modLoaderConsumer().ifPresent(c->c.accept("Completed deep scan of "+this.getFileName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
* 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.progress;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.lwjgl.glfw.GLFWErrorCallback;
|
||||
import org.lwjgl.glfw.GLFWVidMode;
|
||||
import org.lwjgl.opengl.GL;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
import org.lwjgl.stb.STBEasyFont;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryUsage;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.List;
|
||||
|
||||
import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
|
||||
import static org.lwjgl.glfw.GLFW.*;
|
||||
import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
|
||||
import static org.lwjgl.opengl.GL11.*;
|
||||
import static org.lwjgl.system.MemoryStack.stackPush;
|
||||
import static org.lwjgl.system.MemoryUtil.NULL;
|
||||
|
||||
class ClientVisualization implements EarlyProgressVisualization.Visualization {
|
||||
private final int screenWidth = 800;
|
||||
private final int screenHeight = 400;
|
||||
private long window;
|
||||
private Thread thread;
|
||||
private boolean running;
|
||||
|
||||
private void initWindow() {
|
||||
GLFWErrorCallback.createPrint(System.err).set();
|
||||
|
||||
if (!glfwInit()) {
|
||||
throw new IllegalStateException("Unable to initialize GLFW");
|
||||
}
|
||||
|
||||
glfwDefaultWindowHints();
|
||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||
|
||||
window = glfwCreateWindow(screenWidth, screenHeight, "FML early loading progress", NULL, NULL);
|
||||
if (window == NULL) {
|
||||
throw new RuntimeException("Failed to create the GLFW window"); // ignore it and make the GUI optional?
|
||||
}
|
||||
|
||||
try (MemoryStack stack = stackPush()) {
|
||||
IntBuffer pWidth = stack.mallocInt(1);
|
||||
IntBuffer pHeight = stack.mallocInt(1);
|
||||
IntBuffer monPosLeft = stack.mallocInt(1);
|
||||
IntBuffer monPosTop = stack.mallocInt(1);
|
||||
glfwGetWindowSize(window, pWidth, pHeight);
|
||||
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
|
||||
glfwGetMonitorPos(glfwGetPrimaryMonitor(), monPosLeft, monPosTop);
|
||||
// Center the window
|
||||
glfwSetWindowPos(
|
||||
window,
|
||||
(vidmode.width() - pWidth.get(0)) / 2 + monPosLeft.get(0),
|
||||
(vidmode.height() - pHeight.get(0)) / 2 + monPosTop.get(0)
|
||||
);
|
||||
}
|
||||
glfwMakeContextCurrent(window);
|
||||
glfwSwapInterval(1);
|
||||
glfwShowWindow(window);
|
||||
GL.createCapabilities();
|
||||
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
private void renderProgress() {
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0.0D, screenWidth, screenHeight, 0.0D, -1000.0D, 1000.0D);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
// // replace with more modern opengl?
|
||||
// glBegin(GL_QUADS);
|
||||
// glColor3f(0.1f, 0.1f, 0.9f);
|
||||
// glVertex2f(0, 0);
|
||||
// glVertex2f(0, screenHeight);
|
||||
// glVertex2f(screenWidth * progress, screenHeight);
|
||||
// glVertex2f(screenWidth * progress, 0);
|
||||
// glEnd();
|
||||
|
||||
glEnableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
glEnable(GL_BLEND);
|
||||
renderMessages();
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
private static float clamp(float num, float min, float max) {
|
||||
if (num < min) {
|
||||
return min;
|
||||
} else {
|
||||
return num > max ? max : num;
|
||||
}
|
||||
}
|
||||
|
||||
private static int clamp(int num, int min, int max) {
|
||||
if (num < min) {
|
||||
return min;
|
||||
} else {
|
||||
return num > max ? max : num;
|
||||
}
|
||||
}
|
||||
|
||||
private static int hsvToRGB(float hue, float saturation, float value) {
|
||||
int i = (int)(hue * 6.0F) % 6;
|
||||
float f = hue * 6.0F - (float)i;
|
||||
float f1 = value * (1.0F - saturation);
|
||||
float f2 = value * (1.0F - f * saturation);
|
||||
float f3 = value * (1.0F - (1.0F - f) * saturation);
|
||||
float f4;
|
||||
float f5;
|
||||
float f6;
|
||||
switch(i) {
|
||||
case 0:
|
||||
f4 = value;
|
||||
f5 = f3;
|
||||
f6 = f1;
|
||||
break;
|
||||
case 1:
|
||||
f4 = f2;
|
||||
f5 = value;
|
||||
f6 = f1;
|
||||
break;
|
||||
case 2:
|
||||
f4 = f1;
|
||||
f5 = value;
|
||||
f6 = f3;
|
||||
break;
|
||||
case 3:
|
||||
f4 = f1;
|
||||
f5 = f2;
|
||||
f6 = value;
|
||||
break;
|
||||
case 4:
|
||||
f4 = f3;
|
||||
f5 = f1;
|
||||
f6 = value;
|
||||
break;
|
||||
case 5:
|
||||
f4 = value;
|
||||
f5 = f1;
|
||||
f6 = f2;
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Something went wrong when converting from HSV to RGB. Input was " + hue + ", " + saturation + ", " + value);
|
||||
}
|
||||
|
||||
int j = clamp((int)(f4 * 255.0F), 0, 255);
|
||||
int k = clamp((int)(f5 * 255.0F), 0, 255);
|
||||
int l = clamp((int)(f6 * 255.0F), 0, 255);
|
||||
return j << 16 | k << 8 | l;
|
||||
}
|
||||
|
||||
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 = 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(), ((screenHeight - 15) / 20) - 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 = 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, 1, 1.0f);
|
||||
}
|
||||
|
||||
private void renderMessage(final String message, final float[] colour, int row, float alpha) {
|
||||
ByteBuffer charBuffer = MemoryUtil.memAlloc(message.length() * 270);
|
||||
int quads = STBEasyFont.stb_easy_font_print(0, 0, message, null, charBuffer);
|
||||
|
||||
glVertexPointer(3, GL11.GL_FLOAT, 16, charBuffer);
|
||||
glEnable(GL_BLEND);
|
||||
GL14.glBlendColor(0,0,0, alpha);
|
||||
glBlendFunc(GL14.GL_CONSTANT_ALPHA, GL14.GL_ONE_MINUS_CONSTANT_ALPHA);
|
||||
glColor3f(colour[0], colour[1], colour[2]);
|
||||
glPushMatrix();
|
||||
glTranslatef(10, row * 20, 0);
|
||||
glScalef(2, 2, 1);
|
||||
glDrawArrays(GL11.GL_QUADS, 0, quads * 4);
|
||||
glPopMatrix();
|
||||
MemoryUtil.memFree(charBuffer);
|
||||
}
|
||||
|
||||
private void closeWindow() {
|
||||
glfwFreeCallbacks(window);
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
glfwSetErrorCallback(null).free();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
thread = new Thread(this::run);
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
private void run() {
|
||||
initWindow();
|
||||
running = true;
|
||||
while (running) {
|
||||
renderProgress();
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
closeWindow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void join() {
|
||||
// try {
|
||||
// Thread.sleep(10000);
|
||||
// } catch (InterruptedException e) {
|
||||
// }
|
||||
running = false;
|
||||
try {
|
||||
thread.join();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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.progress;
|
||||
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public enum EarlyProgressVisualization {
|
||||
INSTANCE;
|
||||
|
||||
private Visualization visualization;
|
||||
|
||||
public void accept(final Dist dist) {
|
||||
if (visualization != null) return;
|
||||
// We don't show the window on Mac because mac is super mega triple shit and can't handle anything out of the ordinary
|
||||
final boolean ismac = System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("mac");
|
||||
visualization = dist.isClient() && !ismac && Boolean.parseBoolean(System.getProperty("fml.earlyprogresswindow", "true")) ? new ClientVisualization() : new NoVisualization();
|
||||
visualization.start();
|
||||
}
|
||||
|
||||
public void join() {
|
||||
visualization.join();
|
||||
}
|
||||
|
||||
interface Visualization {
|
||||
void start();
|
||||
void join();
|
||||
}
|
||||
|
||||
private static class NoVisualization implements Visualization {
|
||||
@Override
|
||||
public void start() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void join() {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* 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.progress;
|
||||
|
||||
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),
|
||||
LOC(0.0f, 0.5f, 0.0f),
|
||||
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));
|
||||
}
|
||||
|
||||
public static Optional<Consumer<String>> modLoaderConsumer() {
|
||||
return Optional.of(s-> messages.get(MessageType.ML).add(new Message(s, MessageType.ML)));
|
||||
}
|
||||
|
||||
public static Optional<Consumer<String>> locatorConsumer() {
|
||||
return Optional.of(s -> messages.get(MessageType.LOC).add(new Message(s, MessageType.LOC)));
|
||||
}
|
||||
|
||||
static Optional<Consumer<String>> mcLoaderConsumer() {
|
||||
return Optional.of(s-> messages.get(MessageType.MC).add(new Message(s, MessageType.MC)));
|
||||
}
|
||||
}
|
|
@ -20,10 +20,10 @@
|
|||
<Appenders>
|
||||
<TerminalConsole name="Console">
|
||||
<PatternLayout>
|
||||
<LoggerNamePatternSelector defaultPattern="%highlightError{[%d{HH:mm:ss}] [%t/%level] [%c{2.}/%markerSimpleName]: %minecraftFormatting{%msg}%n%tEx}">
|
||||
<LoggerNamePatternSelector defaultPattern="%highlight{[%d{HH:mm:ss}] [%t/%level] [%c{2.}/%markerSimpleName]: %minecraftFormatting{%msg}%n%tEx}">
|
||||
<!-- don't include the full logger name for Mojang's logs since they use full class names and it's very verbose -->
|
||||
<PatternMatch key="net.minecraft." pattern="%highlightError{[%d{HH:mm:ss}] [%t/%level] [minecraft/%logger{1}]: %minecraftFormatting{%msg}%n%tEx}"/>
|
||||
<PatternMatch key="com.mojang." pattern="%highlightError{[%d{HH:mm:ss}] [%t/%level] [mojang/%logger{1}]: %minecraftFormatting{%msg}%n%tEx}"/>
|
||||
<PatternMatch key="net.minecraft." pattern="%highlight{[%d{HH:mm:ss}] [%t/%level] [minecraft/%logger{1}]: %minecraftFormatting{%msg}%n%tEx}"/>
|
||||
<PatternMatch key="com.mojang." pattern="%highlight{[%d{HH:mm:ss}] [%t/%level] [mojang/%logger{1}]: %minecraftFormatting{%msg}%n%tEx}"/>
|
||||
</LoggerNamePatternSelector>
|
||||
</PatternLayout>
|
||||
</TerminalConsole>
|
||||
|
|
|
@ -320,13 +320,10 @@ public class ForgeHooksClient
|
|||
default: break;
|
||||
}
|
||||
|
||||
if (line != null)
|
||||
{
|
||||
// if we have a line, render it in the bottom right, above Mojang's copyright line
|
||||
gui.drawString(font, line, width - font.getStringWidth(line) - 2, height - (2 * (font.FONT_HEIGHT + 1)), -1);
|
||||
}
|
||||
forgeStatusLine = line;
|
||||
}
|
||||
|
||||
public static String forgeStatusLine;
|
||||
public static ISound playSound(SoundEngine manager, ISound sound)
|
||||
{
|
||||
PlaySoundEvent e = new PlaySoundEvent(manager, sound);
|
||||
|
|
|
@ -28,6 +28,7 @@ import net.minecraftforge.fml.event.lifecycle.FMLModIdMappingEvent;
|
|||
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
|
||||
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
|
||||
import net.minecraftforge.server.command.ConfigCommand;
|
||||
import net.minecraftforge.server.command.ForgeCommand;
|
||||
import net.minecraftforge.versions.forge.ForgeVersion;
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.stream.IntStream;
|
|||
|
||||
import net.minecraft.resources.IResourceManager;
|
||||
import net.minecraft.resources.IResourceManagerReloadListener;
|
||||
import net.minecraftforge.client.ForgeHooksClient;
|
||||
import net.minecraftforge.versions.forge.ForgeVersion;
|
||||
import net.minecraftforge.versions.mcp.MCPVersion;
|
||||
|
||||
|
@ -35,6 +36,7 @@ public class BrandingControl
|
|||
{
|
||||
private static List<String> brandings;
|
||||
private static List<String> brandingsNoMC;
|
||||
private static List<String> overCopyrightBrandings;
|
||||
|
||||
private static void computeBranding()
|
||||
{
|
||||
|
@ -61,11 +63,24 @@ public class BrandingControl
|
|||
}
|
||||
}
|
||||
|
||||
private static void computeOverCopyrightBrandings() {
|
||||
if (overCopyrightBrandings == null) {
|
||||
ImmutableList.Builder<String> brd = ImmutableList.builder();
|
||||
if (ForgeHooksClient.forgeStatusLine != null) brd.add(ForgeHooksClient.forgeStatusLine);
|
||||
overCopyrightBrandings = brd.build();
|
||||
}
|
||||
}
|
||||
|
||||
public static void forEachLine(boolean includeMC, boolean reverse, BiConsumer<Integer, String> lineConsumer) {
|
||||
final List<String> brandings = getBrandings(includeMC, reverse);
|
||||
IntStream.range(0, brandings.size()).boxed().forEachOrdered(idx -> lineConsumer.accept(idx, brandings.get(idx)));
|
||||
}
|
||||
|
||||
public static void forEachAboveCopyrightLine(BiConsumer<Integer, String> lineConsumer) {
|
||||
computeOverCopyrightBrandings();
|
||||
IntStream.range(0, overCopyrightBrandings.size()).boxed().forEachOrdered(idx->lineConsumer.accept(idx, overCopyrightBrandings.get(idx)));
|
||||
}
|
||||
|
||||
public static String getClientBranding() {
|
||||
return "forge";
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import net.minecraftforge.fml.loading.LoadingModList;
|
|||
import net.minecraftforge.fml.loading.moddiscovery.InvalidModIdentifier;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
|
||||
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
|
||||
import net.minecraftforge.fml.network.FMLNetworkConstants;
|
||||
import net.minecraftforge.fml.network.NetworkRegistry;
|
||||
import net.minecraftforge.forgespi.language.IModInfo;
|
||||
|
|
|
@ -19,85 +19,8 @@
|
|||
|
||||
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)));
|
||||
net.minecraftforge.fml.loading.progress.StartupMessageManager.addModMessage(message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,27 +19,21 @@
|
|||
|
||||
package net.minecraftforge.fml.client;
|
||||
|
||||
import com.google.common.base.Ascii;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import net.minecraft.client.MainWindow;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraftforge.fml.StartupMessageManager;
|
||||
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
import org.lwjgl.stb.STBEasyFont;
|
||||
import org.lwjgl.stb.STBImage;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryMXBean;
|
||||
import java.lang.management.MemoryUsage;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class EarlyLoaderGUI {
|
||||
private final MainWindow window;
|
||||
|
|
Loading…
Reference in a new issue