Clean progress bar code and fix TextureMap patch (#5304)

This commit is contained in:
mezz 2018-12-28 18:05:05 -08:00 committed by GitHub
parent b4cf6f7f36
commit dc12cda505
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 632 additions and 290 deletions

View file

@ -24,7 +24,7 @@
this.field_110451_am.func_199006_a(new GrassColorReloadListener());
this.field_110451_am.func_199006_a(new FoliageColorReloadListener());
+ net.minecraftforge.fml.common.ProgressManager.ProgressBar bar = net.minecraftforge.fml.common.ProgressManager.push("Rendering Setup", 5, true);
+ try (net.minecraftforge.fml.common.progress.ProgressBar bar = net.minecraftforge.fml.common.progress.StartupProgressManager.start("Rendering Setup", 5, true)) {
+ bar.step("GL Setup");
this.field_195558_d.func_198076_a("Startup");
GlStateManager.func_179098_w();
@ -60,7 +60,7 @@
this.field_71452_i = new ParticleManager(this.field_71441_e, this.field_71446_o);
- this.field_71456_v = new GuiIngame(this);
+ //net.minecraftforge.fml.client.SplashProgress.resume();
+ net.minecraftforge.fml.common.ProgressManager.pop(bar);
+ }; // Forge: end progress bar
+ net.minecraftforge.fml.client.ClientModLoader.end();
+ this.field_71456_v = new net.minecraftforge.client.GuiIngameForge(this);
if (this.field_71475_ae != null) {

View file

@ -21,7 +21,7 @@
}
}
+ net.minecraftforge.fml.common.ProgressManager.ProgressBar resourcesBar = net.minecraftforge.fml.common.ProgressManager.push("Loading sounds", resources.size());
+ try (net.minecraftforge.fml.common.progress.ProgressBar resourcesBar = net.minecraftforge.fml.common.progress.StartupProgressManager.start("Loading sounds", resources.size())) {
+ resources.forEach(entry -> {
+ resourcesBar.step(entry.func_76341_a().toString());
+ try {
@ -30,7 +30,7 @@
+ field_147698_b.warn("Invalid sounds.json", e);
+ }
+ });
+ net.minecraftforge.fml.common.ProgressManager.pop(resourcesBar);
+ }; // Forge: end progress bar
+
for(ResourceLocation resourcelocation : this.field_147697_e.func_148742_b()) {
SoundEventAccessor soundeventaccessor = (SoundEventAccessor)this.field_147697_e.func_82594_a(resourcelocation);

View file

@ -13,9 +13,8 @@
public void func_94305_f() {
Stitcher.Holder[] astitcher$holder = (Stitcher.Holder[])this.field_94319_a.toArray(new Stitcher.Holder[this.field_94319_a.size()]);
Arrays.sort((Object[])astitcher$holder);
-
+ net.minecraftforge.fml.common.ProgressManager.ProgressBar bar = net.minecraftforge.fml.common.ProgressManager.push("Texture stitching", astitcher$holder.length);
+
+ try(net.minecraftforge.fml.common.progress.ProgressBar bar = net.minecraftforge.fml.common.progress.StartupProgressManager.start("Texture stitching", astitcher$holder.length)) {
for(Stitcher.Holder stitcher$holder : astitcher$holder) {
+ bar.step(stitcher$holder.func_98150_a().func_195668_m().toString());
if (!this.func_94310_b(stitcher$holder)) {
@ -29,7 +28,7 @@
this.field_94318_c = MathHelper.func_151236_b(this.field_94318_c);
this.field_94315_d = MathHelper.func_151236_b(this.field_94315_d);
+ net.minecraftforge.fml.common.ProgressManager.pop(bar);
+ }; // Forge: end progress bar
}
public List<TextureAtlasSprite> func_94309_g() {

View file

@ -12,7 +12,7 @@
public void func_195410_a(IResourceManager p_195410_1_) {
MissingTextureSprite.func_195676_d();
+ net.minecraftforge.fml.common.ProgressManager.ProgressBar bar = net.minecraftforge.fml.common.ProgressManager.push("Reloading Texture Manager", this.field_110585_a.entrySet().size(), true);
+ try (net.minecraftforge.fml.common.progress.ProgressBar bar = net.minecraftforge.fml.common.progress.StartupProgressManager.start("Reloading Texture Manager", this.field_110585_a.entrySet().size(), true)) {
Iterator<Entry<ResourceLocation, ITextureObject>> iterator = this.field_110585_a.entrySet().iterator();
while(iterator.hasNext()) {
@ -26,7 +26,7 @@
this.func_110579_a(entry.getKey(), itextureobject);
}
}
+ net.minecraftforge.fml.common.ProgressManager.pop(bar);
+ }; // Forge: end progress bar
+ }
+ @Override

View file

@ -8,113 +8,40 @@
p_195426_2_.forEach((p_195423_2_) -> {
this.func_199362_a(p_195426_1_, p_195423_2_);
});
@@ -56,37 +57,76 @@
this.func_195419_g();
@@ -57,8 +58,14 @@
int j = Integer.MAX_VALUE;
int k = 1 << this.field_147636_j;
-
- for(ResourceLocation resourcelocation : this.field_195427_i) {
+ field_147635_d.info("Max texture size: {}", i);
+ net.minecraftforge.fml.common.ProgressManager.ProgressBar bar = net.minecraftforge.fml.common.ProgressManager.push("Texture stitching", this.field_195427_i.size());
+ try (net.minecraftforge.fml.common.progress.ProgressBar textureLoadingBar = net.minecraftforge.fml.common.progress.StartupProgressManager.start("Texture loading", this.field_195427_i.size())) {
+ loadedSprites.clear();
+
+ for(ResourceLocation resourcelocation : Sets.newHashSet(this.field_195427_i)) {
+ ResourceLocation resourcelocation1 = this.func_195420_b(resourcelocation);
+ bar.step(resourcelocation1.toString());
+ textureLoadingBar.step(this.func_195420_b(resourcelocation).toString());
if (!this.field_94249_f.func_195668_m().equals(resourcelocation)) {
- ResourceLocation resourcelocation1 = this.func_195420_b(resourcelocation);
+ j = loadTexture(stitcher, p_195421_1_, resourcelocation, bar, j, k);
+ }
+ }
+ finishLoading(stitcher, p_195421_1_, bar, j, k);
+ }
+
+ private int loadTexture(Stitcher stitcher, IResourceManager manager, ResourceLocation resourcelocation, net.minecraftforge.fml.common.ProgressManager.ProgressBar bar, int j, int k) {
+ if (loadedSprites.contains(resourcelocation)) {
+ return j;
+ }
+ TextureAtlasSprite textureatlassprite;
+ ResourceLocation resourcelocation1 = this.func_195420_b(resourcelocation);
+ for(ResourceLocation loading : loadingSprites) {
+ if(resourcelocation1.equals(loading)) {
+ final String error = "circular model dependencies, stack: [" + com.google.common.base.Joiner.on(", ").join(loadingSprites) + "]";
+ net.minecraftforge.fml.client.ClientHooks.trackBrokenTexture(resourcelocation, error);
+ }
+ }
+ loadingSprites.addLast(resourcelocation1);
+ try (IResource iresource = manager.func_199002_a(resourcelocation1)) {
+ PngSizeInfo pngsizeinfo = new PngSizeInfo(iresource);
+ AnimationMetadataSection animationmetadatasection = (AnimationMetadataSection)iresource.func_199028_a(AnimationMetadataSection.field_195817_a);
+ textureatlassprite = new TextureAtlasSprite(resourcelocation, pngsizeinfo, animationmetadatasection);
+ j = loadTexture(stitcher, p_195421_1_, resourcelocation, j, k);
+ if (true) continue; // Forge: skip the rest of this if statement, we're using loadTexture instead
ResourceLocation resourcelocation1 = this.func_195420_b(resourcelocation);
- TextureAtlasSprite textureatlassprite;
- try (IResource iresource = p_195421_1_.func_199002_a(resourcelocation1)) {
- PngSizeInfo pngsizeinfo = new PngSizeInfo(iresource);
- AnimationMetadataSection animationmetadatasection = (AnimationMetadataSection)iresource.func_199028_a(AnimationMetadataSection.field_195817_a);
- textureatlassprite = new TextureAtlasSprite(resourcelocation, pngsizeinfo, animationmetadatasection);
- } catch (RuntimeException runtimeexception) {
- field_147635_d.error("Unable to parse metadata from {} : {}", resourcelocation1, runtimeexception);
- continue;
- } catch (IOException ioexception) {
- field_147635_d.error("Using missing texture, unable to load {} : {}", resourcelocation1, ioexception);
- continue;
+ for (ResourceLocation dependency : textureatlassprite.getDependencies()) {
+ if (!field_195427_i.contains(dependency.toString())) {
+ func_199362_a(manager, dependency);
TextureAtlasSprite textureatlassprite;
@@ -84,9 +91,11 @@
stitcher.func_110934_a(textureatlassprite);
}
-
- j = Math.min(j, Math.min(textureatlassprite.func_94211_a(), textureatlassprite.func_94216_b()));
- int j1 = Math.min(Integer.lowestOneBit(textureatlassprite.func_94211_a()), Integer.lowestOneBit(textureatlassprite.func_94216_b()));
- if (j1 < k) {
- field_147635_d.warn("Texture {} with size {}x{} limits mip level from {} to {}", resourcelocation1, textureatlassprite.func_94211_a(), textureatlassprite.func_94216_b(), MathHelper.func_151239_c(k), MathHelper.func_151239_c(j1));
- k = j1;
+ j = loadTexture(stitcher, manager, dependency, bar, j, k);
+ }
+ if (textureatlassprite.hasCustomLoader(manager, resourcelocation)) {
+ if (textureatlassprite.load(manager, resourcelocation, l -> field_94252_e.get(l.toString()))) {
+ return j;
}
-
- stitcher.func_110934_a(textureatlassprite);
}
+ j = Math.min(j, Math.min(textureatlassprite.func_94211_a(), textureatlassprite.func_94216_b()));
+ int j1 = Math.min(Integer.lowestOneBit(textureatlassprite.func_94211_a()), Integer.lowestOneBit(textureatlassprite.func_94216_b()));
+ if (j1 < k) {
+ // FORGE: do not lower the mipmap level, just log the problematic textures
+ field_147635_d.warn("Texture {} with size {}x{} will have visual artifacts at mip level {}, it can only support level {}. Please report to the mod author that the texture should be some multiple of 16x16.", resourcelocation1, textureatlassprite.func_94211_a(), textureatlassprite.func_94216_b(), MathHelper.func_151239_c(k), MathHelper.func_151239_c(j1));
+ }
+ if (func_195422_a(manager, textureatlassprite))
+ stitcher.func_110934_a(textureatlassprite);
+ return j;
+ } catch (RuntimeException runtimeexception) {
+ net.minecraftforge.fml.client.ClientHooks.trackBrokenTexture(resourcelocation, runtimeexception.getMessage());
+ return j;
+ } catch (IOException ioexception) {
+ net.minecraftforge.fml.client.ClientHooks.trackMissingTexture(resourcelocation);
+ return j;
+ } finally {
+ loadingSprites.removeLast();
+ field_195427_i.add(resourcelocation1);
}
-
+ }
+
+ private void finishLoading(Stitcher stitcher, IResourceManager manager, net.minecraftforge.fml.common.ProgressManager.ProgressBar bar, int j, int k)
+ {
+ net.minecraftforge.fml.common.ProgressManager.pop(bar);
+ } // Forge: end progress bar
int l = Math.min(j, k);
int i1 = MathHelper.func_151239_c(l);
+ if (false) // FORGE: do not lower the mipmap level
if (i1 < this.field_147636_j) {
field_147635_d.warn("{}: dropping miplevel from {} to {}, because of minimum power of two: {}", this.field_94254_c, this.field_147636_j, i1, l);
this.field_147636_j = i1;
@@ -94,18 +134,26 @@
@@ -94,18 +103,25 @@
this.field_94249_f.func_147963_d(this.field_147636_j);
stitcher.func_110934_a(this.field_94249_f);
-
+ bar = net.minecraftforge.fml.common.ProgressManager.push("Texture creation", 2);
+
+ try (net.minecraftforge.fml.common.progress.ProgressBar bar = net.minecraftforge.fml.common.progress.StartupProgressManager.start("Texture creation", 2)) {
try {
+ bar.step("Stitching");
stitcher.func_94305_f();
@ -125,28 +52,27 @@
field_147635_d.info("Created: {}x{} {}-atlas", stitcher.func_110935_a(), stitcher.func_110936_b(), this.field_94254_c);
+ bar.step("Allocating GL texture");
TextureUtil.func_180600_a(this.func_110552_b(), this.field_147636_j, stitcher.func_110935_a(), stitcher.func_110936_b());
+
+ net.minecraftforge.fml.common.ProgressManager.pop(bar);
+ bar = net.minecraftforge.fml.common.ProgressManager.push("Texture mipmap and upload", stitcher.func_94309_g().size());
+ }; // Forge: end progress bar
+ try (net.minecraftforge.fml.common.progress.ProgressBar bar = net.minecraftforge.fml.common.progress.StartupProgressManager.start("Texture mipmap and upload", stitcher.func_94309_g().size())) {
for(TextureAtlasSprite textureatlassprite1 : stitcher.func_94309_g()) {
- if (textureatlassprite1 == this.field_94249_f || this.func_195422_a(p_195421_1_, textureatlassprite1)) {
+ bar.step(textureatlassprite1.func_195668_m().toString());
+ // FORGE: Sprite loading is now done during stitching, short-circuit this check
+ if (true || textureatlassprite1 == this.field_94249_f || this.func_195422_a(manager, textureatlassprite1)) {
+ if (true || textureatlassprite1 == this.field_94249_f || this.func_195422_a(p_195421_1_, textureatlassprite1)) {
this.field_94252_e.put(textureatlassprite1.func_195668_m(), textureatlassprite1);
try {
@@ -124,6 +172,8 @@
@@ -124,6 +140,8 @@
}
}
+ net.minecraftforge.client.ForgeHooksClient.onTextureStitchedPost(this);
+ net.minecraftforge.fml.common.ProgressManager.pop(bar);
+ }; // Forge: end progress bar
}
private boolean func_195422_a(IResourceManager p_195422_1_, TextureAtlasSprite p_195422_2_) {
@@ -132,6 +182,7 @@
@@ -132,6 +150,7 @@
label62: {
boolean flag;
@ -154,7 +80,7 @@
try {
iresource = p_195422_1_.func_199002_a(resourcelocation);
p_195422_2_.func_195664_a(iresource, this.field_147636_j + 1);
@@ -216,4 +267,21 @@
@@ -216,4 +235,91 @@
this.field_94252_e.clear();
this.field_94258_i.clear();
}
@ -174,5 +100,75 @@
+ public int getMipmapLevels()
+ {
+ return field_147636_j;
+ }
+
+ private int loadTexture(Stitcher stitcher, IResourceManager manager, ResourceLocation resourcelocation, int j, int k)
+ {
+ if (loadedSprites.contains(resourcelocation))
+ {
+ return j;
+ }
+ TextureAtlasSprite textureatlassprite;
+ ResourceLocation resourcelocation1 = this.func_195420_b(resourcelocation);
+ for (ResourceLocation loading : loadingSprites)
+ {
+ if (resourcelocation1.equals(loading))
+ {
+ final String error = "circular model dependencies, stack: [" + com.google.common.base.Joiner.on(", ").join(loadingSprites) + "]";
+ net.minecraftforge.fml.client.ClientHooks.trackBrokenTexture(resourcelocation, error);
+ }
+ }
+ loadingSprites.addLast(resourcelocation1);
+ try (IResource iresource = manager.func_199002_a(resourcelocation1))
+ {
+ PngSizeInfo pngsizeinfo = new PngSizeInfo(iresource);
+ AnimationMetadataSection animationmetadatasection = iresource.func_199028_a(AnimationMetadataSection.field_195817_a);
+ textureatlassprite = new TextureAtlasSprite(resourcelocation, pngsizeinfo, animationmetadatasection);
+
+ for (ResourceLocation dependency : textureatlassprite.getDependencies())
+ {
+ if (!field_195427_i.contains(dependency))
+ {
+ func_199362_a(manager, dependency);
+ }
+ j = loadTexture(stitcher, manager, dependency, j, k);
+ }
+ if (textureatlassprite.hasCustomLoader(manager, resourcelocation))
+ {
+ if (textureatlassprite.load(manager, resourcelocation, field_94252_e::get))
+ {
+ return j;
+ }
+ }
+ j = Math.min(j, Math.min(textureatlassprite.func_94211_a(), textureatlassprite.func_94216_b()));
+ int j1 = Math.min(Integer.lowestOneBit(textureatlassprite.func_94211_a()), Integer.lowestOneBit(textureatlassprite.func_94216_b()));
+ if (j1 < k)
+ {
+ // FORGE: do not lower the mipmap level, just log the problematic textures
+ field_147635_d.warn("Texture {} with size {}x{} will have visual artifacts at mip level {}, it can only support level {}." +
+ "Please report to the mod author that the texture should be some multiple of 16x16.",
+ resourcelocation1, textureatlassprite.func_94211_a(), textureatlassprite.func_94216_b(), MathHelper.func_151239_c(k), MathHelper.func_151239_c(j1));
+ }
+ if (func_195422_a(manager, textureatlassprite))
+ {
+ stitcher.func_110934_a(textureatlassprite);
+ }
+ return j;
+ }
+ catch (RuntimeException runtimeexception)
+ {
+ net.minecraftforge.fml.client.ClientHooks.trackBrokenTexture(resourcelocation, runtimeexception.getMessage());
+ return j;
+ }
+ catch (IOException ioexception)
+ {
+ net.minecraftforge.fml.client.ClientHooks.trackMissingTexture(resourcelocation);
+ return j;
+ }
+ finally
+ {
+ loadingSprites.removeLast();
+ field_195427_i.add(resourcelocation1);
+ }
+ }
}

View file

@ -12,7 +12,7 @@
}
public void func_199005_a(List<IResourcePack> p_199005_1_) {
+ net.minecraftforge.fml.common.ProgressManager.ProgressBar resReload = net.minecraftforge.fml.common.ProgressManager.push("Loading Resources", p_199005_1_.size() + 1, true);
+ try (net.minecraftforge.fml.common.progress.ProgressBar resReload = net.minecraftforge.fml.common.progress.StartupProgressManager.start("Loading Resources", p_199005_1_.size() + 1, true)) {
this.func_199008_b();
field_199012_a.info("Reloading ResourceManager: {}", p_199005_1_.stream().map(IResourcePack::func_195762_a).collect(Collectors.joining(", ")));
@ -27,12 +27,12 @@
} else {
this.func_199010_c();
}
+ net.minecraftforge.fml.common.ProgressManager.pop(resReload);
+ }; // Forge: end progress bar
}
public void func_199006_a(IResourceManagerReloadListener p_199006_1_) {
+ net.minecraftforge.fml.common.ProgressManager.ProgressBar resReload = net.minecraftforge.fml.common.ProgressManager.push("Loading Resource", 1);
+ try (net.minecraftforge.fml.common.progress.ProgressBar resReload = net.minecraftforge.fml.common.progress.StartupProgressManager.start("Loading Resource", 1)) {
+ resReload.step(p_199006_1_.getClass());
this.field_199015_d.add(p_199006_1_);
if (field_199012_a.isDebugEnabled()) {
@ -40,18 +40,18 @@
} else {
p_199006_1_.func_195410_a(this);
}
+ net.minecraftforge.fml.common.ProgressManager.pop(resReload);
+ }; // Forge: end progress bar
}
private void func_199010_c() {
+ net.minecraftforge.fml.common.ProgressManager.ProgressBar resReload = net.minecraftforge.fml.common.ProgressManager.push("Reloading", this.field_199015_d.size());
+ try (net.minecraftforge.fml.common.progress.ProgressBar resReload = net.minecraftforge.fml.common.progress.StartupProgressManager.start("Reloading", this.field_199015_d.size())) {
for(IResourceManagerReloadListener iresourcemanagerreloadlistener : this.field_199015_d) {
+ resReload.step(iresourcemanagerreloadlistener.getClass());
+ if (!net.minecraftforge.resource.SelectiveReloadStateHandler.INSTANCE.test(iresourcemanagerreloadlistener)) continue; // Forge: Selective reloading for vanilla listeners
iresourcemanagerreloadlistener.func_195410_a(this);
}
+ net.minecraftforge.fml.common.ProgressManager.pop(resReload);
+ }; // Forge: end progress bar
}

View file

@ -89,8 +89,6 @@ import net.minecraftforge.common.property.IExtendedBlockState;
import net.minecraftforge.common.property.Properties;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fml.client.ClientModLoader;
import net.minecraftforge.fml.common.ProgressManager;
import net.minecraftforge.fml.common.ProgressManager.ProgressBar;
import net.minecraftforge.logging.ModelLoaderErrorMessage;
import net.minecraftforge.registries.IRegistryDelegate;

View file

@ -34,13 +34,23 @@ import java.util.function.Supplier;
public enum SidedProvider
{
// All of these need to be careful not to directly dereference the client and server elements in their signatures
DATAFIXER(c->c.get().getDataFixer(), s->s.get().getDataFixer()),
SIDEDINIT((Function<Supplier<Minecraft>, Function<ModContainer, Event>>)c-> mc->new FMLClientInitEvent(c, mc),
(Function<Supplier<DedicatedServer>, Function<ModContainer, Event>>)s-> mc->new FMLServerInitEvent(s, mc)),
STRIPCHARS((Function<Supplier<Minecraft>, Function<String, String>>)c-> ClientHooks::stripSpecialChars,
(Function<Supplier<DedicatedServer>, Function<String, String>>)s-> str->str),
DATAFIXER(
c->c.get().getDataFixer(),
s->s.get().getDataFixer(),
()-> { throw new UnsupportedOperationException(); }),
SIDEDINIT(
(Function<Supplier<Minecraft>, Function<ModContainer, Event>>)c-> mc->new FMLClientInitEvent(c, mc),
s-> mc->new FMLServerInitEvent(s, mc),
()-> { throw new UnsupportedOperationException(); }),
STRIPCHARS(
(Function<Supplier<Minecraft>, Function<String, String>>)c-> ClientHooks::stripSpecialChars,
s-> str->str,
()-> str->str),
@SuppressWarnings("Convert2MethodRef") // need to not be methodrefs to avoid classloading all of StartupQuery's data (supplier is coming from StartupQuery)
STARTUPQUERY(c->StartupQuery.QueryWrapper.clientQuery(c), s->StartupQuery.QueryWrapper.dedicatedServerQuery(s));
STARTUPQUERY(
c->StartupQuery.QueryWrapper.clientQuery(c),
s->StartupQuery.QueryWrapper.dedicatedServerQuery(s),
()-> { throw new UnsupportedOperationException(); });
private static Supplier<Minecraft> client;
private static Supplier<DedicatedServer> server;
@ -56,12 +66,13 @@ public enum SidedProvider
private final Function<Supplier<Minecraft>, ?> clientSide;
private final Function<Supplier<DedicatedServer>, ?> serverSide;
private final Supplier<?> testSide;
SidedProvider(Function<Supplier<Minecraft>,?> clientSide, Function<Supplier<DedicatedServer>,?> serverSide)
<T> SidedProvider(Function<Supplier<Minecraft>, T> clientSide, Function<Supplier<DedicatedServer>, T> serverSide, Supplier<T> testSide)
{
this.clientSide = clientSide;
this.serverSide = serverSide;
this.testSide = testSide;
}
@SuppressWarnings("unchecked")
@ -73,7 +84,7 @@ public enum SidedProvider
return (T)this.serverSide.apply(server);
}
else {
throw new IllegalArgumentException("THREE SIDES? WUT?");
return (T)this.testSide.get();
}
}
}

View file

@ -125,8 +125,10 @@ public class SplashProgress
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() {
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
@ -134,9 +136,9 @@ public class SplashProgress
if (!SplashProgress.mutex.tryAcquire()) return null;
Display.processMessages();
SplashProgress.mutex.release();
return null;
*/
}
/*
private static String getString(String name, String def)
{
String value = config.getProperty(name, def);
@ -448,9 +450,10 @@ public class SplashProgress
drawBox(barWidth - 2, barHeight - 2);
// slidy part
setColor(barColor);
drawBox((barWidth - 2) * (b.getStep() + 1) / (b.getSteps() + 1), barHeight - 2); // Step can sometimes be 0.
int step = b.getStep();
drawBox((barWidth - 2) * (step + 1) / (b.getTotalSteps() + 1), barHeight - 2); // Step can sometimes be 0.
// progress text
String progress = "" + b.getStep() + "/" + b.getSteps();
String progress = "" + step + "/" + b.getTotalSteps();
glTranslatef(((float)barWidth - 2) / 2 - fontRenderer.getStringWidth(progress), 2, 0);
setColor(fontColor);
glScalef(2, 2, 1);

View file

@ -1,162 +0,0 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* 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;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Function;
import java.util.stream.Collectors;
import net.minecraftforge.fml.SidedProvider;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.MessageFormatMessage;
import static net.minecraftforge.fml.Logging.SPLASH;
/**
* Not a fully fleshed out API, may change in future MC versions.
* However feel free to use and suggest additions.
*/
public class ProgressManager
{
private static final Logger LOGGER = LogManager.getLogger();
private static final List<ProgressBar> bars = new CopyOnWriteArrayList<ProgressBar>();
/**
* Not a fully fleshed out API, may change in future MC versions.
* However feel free to use and suggest additions.
*/
public static ProgressBar push(String title, int steps)
{
return push(title, steps, false);
}
/**
* Not a fully fleshed out API, may change in future MC versions.
* However feel free to use and suggest additions.
*/
public static ProgressBar push(String title, int steps, boolean timeEachStep)
{
ProgressBar bar = new ProgressBar(title, steps);
bars.add(bar);
if (timeEachStep)
{
bar.timeEachStep();
}
// DistExecutor.runWhenOn(Dist.CLIENT, ()->SplashProgress::processMessages);
return bar;
}
/**
* Not a fully fleshed out API, may change in future MC versions.
* However feel free to use and suggest additions.
*/
public static void pop(ProgressBar bar)
{
if(bar.getSteps() != bar.getStep()) throw new IllegalStateException("can't pop unfinished ProgressBar " + bar.getTitle());
bars.remove(bar);
if (bar.getSteps() != 0)
{
long newTime = System.nanoTime();
if (bar.timeEachStep)
LOGGER.debug(SPLASH, () -> new MessageFormatMessage("Bar Step: {0} - {1} took {2,number,0.000}ms", bar.getTitle(), bar.getMessage(), (newTime - bar.lastTime) / 1.0e6));
if (bar.getSteps() == 1)
LOGGER.debug(SPLASH, () -> new MessageFormatMessage("Bar Finished: {0} - {1} took {2,number,0.000}ms", bar.getTitle(), bar.getMessage(), (newTime - bar.lastTime) / 1.0e6));
else
LOGGER.debug(SPLASH, () -> new MessageFormatMessage("Bar Finished: {0} took {1,number,0.000}ms", bar.getTitle(), (newTime - bar.lastTime) / 1.0e6));
}
// DistExecutor.runWhenOn(Dist.CLIENT, ()->SplashProgress::processMessages);
}
/*
* Internal use only.
*/
public static Iterator<ProgressBar> barIterator()
{
return bars.iterator();
}
/**
* Not a fully fleshed out API, may change in future MC versions.
* However feel free to use and suggest additions.
*/
public static class ProgressBar
{
private final String title;
private final int steps;
private volatile int step = 0;
private volatile String message = "";
private boolean timeEachStep = false;
private long startTime = System.nanoTime();
private long lastTime = startTime;
private ProgressBar(String title, int steps)
{
this.title = title;
this.steps = steps;
}
public void step(Class<?> classToName, String... extra)
{
step(ClassNameUtils.shortName(classToName)+ String.join(" ", extra));
}
public void step(String message)
{
if(step >= steps) throw new IllegalStateException("too much steps for ProgressBar " + title);
if (timeEachStep && step != 0)
{
long newTime = System.nanoTime();
LOGGER.debug(SPLASH,new MessageFormatMessage("Bar Step: {0} - {1} took {2,number,0.000}ms", getTitle(), getMessage(), (newTime - lastTime) / 1.0e6));
lastTime = newTime;
}
step += 1;
this.message = SidedProvider.STRIPCHARS.<Function<String, String>>get().apply(message);
}
public String getTitle()
{
return title;
}
public int getSteps()
{
return steps;
}
public int getStep()
{
return step;
}
public String getMessage()
{
return message;
}
public void timeEachStep()
{
this.timeEachStep = true;
}
}
}

View file

@ -0,0 +1,31 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* 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) {}
}

View file

@ -0,0 +1,98 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* 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);
}
}

View file

@ -0,0 +1,129 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* 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();
}
}

View file

@ -0,0 +1,63 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* 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();
}
}

View file

@ -0,0 +1,176 @@
package net.minecraftforge.test;
import net.minecraftforge.fml.common.progress.IProgressBarTracker;
import net.minecraftforge.fml.common.progress.ProgressBar;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class TestProgressBar
{
private static String getStepMessage(int step)
{
if (step == 0)
{
return "";
}
return "testStep" + step;
}
private static void checkBarState(int step, String message, int expectedStepValue, int totalSteps)
{
if (step != expectedStepValue)
{
throw new IllegalStateException("Got step " + step + " but expected " + expectedStepValue);
}
if (step > totalSteps)
{
throw new IllegalStateException("ProgressBar stepped past the total: " + step + "/" + totalSteps);
}
String expectedMessage = getStepMessage(expectedStepValue);
if (!message.equals(expectedMessage))
{
throw new IllegalStateException("Got message '" + message + "' but expected '" + expectedMessage + "'");
}
}
@Test
public void testProgressBar()
{
String title = "testTitle";
final int totalSteps = 20;
IProgressBarTracker tracker = new TestProgressBarTracker(totalSteps, title);
try (ProgressBar progressBar = new ProgressBar(title, totalSteps, s -> s, tracker))
{
String barTitle = progressBar.getTitle();
if (!title.equals(barTitle))
{
throw new IllegalStateException("Got title " + barTitle + " but expected " + title);
}
for (int i = 1; i <= totalSteps; i++) {
progressBar.step(getStepMessage(i));
}
}
}
@Test
public void testThreadedProgressBar()
{
String title = "testTitle";
final int totalSteps = 10;
TestProgressBarTracker tracker = new TestProgressBarTracker(totalSteps, title);
AtomicBoolean threadSawBar = new AtomicBoolean(false);
Thread thread = new Thread(() ->
{
List<ProgressBar> bars = TestProgressBarTracker.getBars();
while (bars.isEmpty())
{
Thread.yield();
bars = TestProgressBarTracker.getBars();
}
while (!bars.isEmpty())
{
for (ProgressBar bar : bars)
{
Pair<Integer, String> stepAndMessage = bar.getStepAndMessage();
int step = stepAndMessage.getLeft();
String message = stepAndMessage.getRight();
checkBarState(step, message, step, totalSteps);
threadSawBar.set(true);
}
Thread.yield();
bars = TestProgressBarTracker.getBars();
}
});
thread.start();
try (ProgressBar progressBar = new ProgressBar(title, totalSteps, s -> s, tracker))
{
String barTitle = progressBar.getTitle();
if (!title.equals(barTitle))
{
throw new IllegalStateException("Got title " + barTitle + " but expected " + title);
}
for (int i = 1; i <= totalSteps; i++) {
progressBar.step(getStepMessage(i));
try
{
Thread.sleep(1);
}
catch (InterruptedException ignored)
{
}
}
}
if (!threadSawBar.get())
{
throw new IllegalStateException("Thread never saw any progress bars");
}
}
private static class TestProgressBarTracker implements IProgressBarTracker
{
private static final List<ProgressBar> bars = new CopyOnWriteArrayList<>();
private final AtomicInteger stepped = new AtomicInteger(0);
private final int totalSteps;
private final String title;
public TestProgressBarTracker(int totalSteps, String title)
{
this.totalSteps = totalSteps;
this.title = title;
}
@Override
public void onBarCreated(ProgressBar bar)
{
bars.add(bar);
int expectedStepCount = 0;
Pair<Integer, String> stepAndMessage = bar.getStepAndMessage();
Integer step = stepAndMessage.getLeft();
String message = stepAndMessage.getRight();
checkBarState(step, message, expectedStepCount, totalSteps);
}
@Override
public void onStepStarted(ProgressBar bar, int step, String message)
{
int expectedStepCount = stepped.incrementAndGet();
checkBarState(step, message, expectedStepCount, totalSteps);
}
@Override
public void onStepFinished(ProgressBar bar, int step, String message)
{
int expectedStepCount = stepped.get();
checkBarState(step, message, expectedStepCount, totalSteps);
}
@Override
public void onBarFinished(ProgressBar bar, int step, String message)
{
bars.remove(bar);
int expectedStepCount = stepped.get();
checkBarState(step, message, expectedStepCount, totalSteps);
if (step != totalSteps)
{
throw new IllegalStateException("ProgressBar did not finish: " + title + ".\nSteps: " + step + "/" + totalSteps);
}
}
public static List<ProgressBar> getBars()
{
return bars;
}
}
}