--- ../src-base/minecraft/net/minecraft/client/renderer/texture/TextureMap.java +++ ../src-work/minecraft/net/minecraft/client/renderer/texture/TextureMap.java @@ -45,6 +45,16 @@ public TextureMap(String p_i46100_1_, @Nullable ITextureMapPopulator p_i46100_2_) { + this(p_i46100_1_, p_i46100_2_, false); + } + + public TextureMap(String basePathIn, boolean skipFirst) + { + this(basePathIn, null, skipFirst); + } + + public TextureMap(String p_i46100_1_, @Nullable ITextureMapPopulator p_i46100_2_, boolean skipFirst) + { this.field_94258_i = Lists.newArrayList(); this.field_110574_e = Maps.newHashMap(); this.field_94252_e = Maps.newHashMap(); @@ -74,6 +84,7 @@ public void func_174943_a(IResourceManager p_174943_1_, ITextureMapPopulator p_174943_2_) { this.field_110574_e.clear(); + net.minecraftforge.client.ForgeHooksClient.onTextureStitchedPre(this); p_174943_2_.func_177059_a(this); this.func_110569_e(); this.func_147631_c(); @@ -88,13 +99,55 @@ this.field_94258_i.clear(); int j = Integer.MAX_VALUE; int k = 1 << this.field_147636_j; + net.minecraftforge.fml.common.FMLLog.log.info("Max texture size: {}", i); + net.minecraftforge.fml.common.ProgressManager.ProgressBar bar = net.minecraftforge.fml.common.ProgressManager.push("Texture stitching", this.field_110574_e.size()); + loadedSprites.clear(); - for (Entry entry : this.field_110574_e.entrySet()) + for (Entry entry : Maps.newHashMap(this.field_110574_e).entrySet()) { - TextureAtlasSprite textureatlassprite = entry.getValue(); - ResourceLocation resourcelocation = this.func_184396_a(textureatlassprite); - IResource iresource = null; + final ResourceLocation location = new ResourceLocation(entry.getKey()); + bar.step(location.toString()); + j = loadTexture(stitcher, p_110571_1_, location, entry.getValue(), bar, j, k); + } + finishLoading(stitcher, bar, j, k); + } + private int loadTexture(Stitcher stitcher, IResourceManager p_110571_1_, ResourceLocation location, TextureAtlasSprite textureatlassprite, net.minecraftforge.fml.common.ProgressManager.ProgressBar bar, int j, int k) + { + if (loadedSprites.contains(location)) { + return j; + } + ResourceLocation resourcelocation = this.func_184396_a(textureatlassprite); + IResource iresource = null; + + for(ResourceLocation loading : loadingSprites) + { + if(location.equals(loading)) + { + final String error = "circular model dependencies, stack: [" + com.google.common.base.Joiner.on(", ").join(loadingSprites) + "]"; + net.minecraftforge.fml.client.FMLClientHandler.instance().trackBrokenTexture(resourcelocation, error); + } + } + loadingSprites.addLast(location); + try + { + for (ResourceLocation dependency : textureatlassprite.getDependencies()) + { + if (!field_110574_e.containsKey(dependency.toString())) + { + func_174942_a(dependency); + } + TextureAtlasSprite depSprite = field_110574_e.get(dependency.toString()); + j = loadTexture(stitcher, p_110571_1_, dependency, depSprite, bar, j, k); + } + if (textureatlassprite.hasCustomLoader(p_110571_1_, resourcelocation)) + { + if (textureatlassprite.load(p_110571_1_, resourcelocation, l -> field_110574_e.get(l.toString()))) + { + return j; + } + } + else try { PngSizeInfo pngsizeinfo = PngSizeInfo.func_188532_a(p_110571_1_.func_110536_a(resourcelocation)); @@ -104,13 +157,13 @@ } catch (RuntimeException runtimeexception) { - field_147635_d.error("Unable to parse metadata from {}", resourcelocation, runtimeexception); - continue; + net.minecraftforge.fml.client.FMLClientHandler.instance().trackBrokenTexture(resourcelocation, runtimeexception.getMessage()); + return j; } catch (IOException ioexception) { - field_147635_d.error("Using missing texture, unable to load {}", resourcelocation, ioexception); - continue; + net.minecraftforge.fml.client.FMLClientHandler.instance().trackMissingTexture(resourcelocation); + return j; } finally { @@ -122,16 +175,28 @@ if (j1 < k) { - field_147635_d.warn("Texture {} with size {}x{} limits mip level from {} to {}", resourcelocation, Integer.valueOf(textureatlassprite.func_94211_a()), Integer.valueOf(textureatlassprite.func_94216_b()), Integer.valueOf(MathHelper.func_151239_c(k)), Integer.valueOf(MathHelper.func_151239_c(j1))); - k = j1; + // 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.", resourcelocation, Integer.valueOf(textureatlassprite.func_94211_a()), Integer.valueOf(textureatlassprite.func_94216_b()), Integer.valueOf(MathHelper.func_151239_c(k)), Integer.valueOf(MathHelper.func_151239_c(j1))); } + if (func_184397_a(p_110571_1_, textureatlassprite)) stitcher.func_110934_a(textureatlassprite); + return j; } + finally + { + loadingSprites.removeLast(); + loadedSprites.add(location); + } + } + private void finishLoading(Stitcher stitcher, net.minecraftforge.fml.common.ProgressManager.ProgressBar bar, int j, int k) + { + net.minecraftforge.fml.common.ProgressManager.pop(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, Integer.valueOf(this.field_147636_j), Integer.valueOf(i1), Integer.valueOf(l)); @@ -140,9 +205,11 @@ 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 { + bar.step("Stitching"); stitcher.func_94305_f(); } catch (StitcherException stitcherexception) @@ -151,12 +218,16 @@ } field_147635_d.info("Created: {}x{} {}-atlas", Integer.valueOf(stitcher.func_110935_a()), Integer.valueOf(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()); Map map = Maps.newHashMap(this.field_110574_e); + net.minecraftforge.fml.common.ProgressManager.pop(bar); + bar = net.minecraftforge.fml.common.ProgressManager.push("Texture mipmap and upload", stitcher.func_94309_g().size()); + for (TextureAtlasSprite textureatlassprite1 : stitcher.func_94309_g()) { - if (textureatlassprite1 == this.field_94249_f || this.func_184397_a(p_110571_1_, textureatlassprite1)) + bar.step(textureatlassprite1.func_94215_i()); { String s = textureatlassprite1.func_94215_i(); map.remove(s); @@ -186,6 +257,8 @@ { textureatlassprite2.func_94217_a(this.field_94249_f); } + net.minecraftforge.client.ForgeHooksClient.onTextureStitchedPost(this); + net.minecraftforge.fml.common.ProgressManager.pop(bar); } private boolean func_184397_a(IResourceManager p_184397_1_, final TextureAtlasSprite p_184397_2_) @@ -195,7 +268,7 @@ label62: { boolean flag; - + if (p_184397_2_.hasCustomLoader(p_184397_1_, resourcelocation)) break label62; try { iresource = p_184397_1_.func_110536_a(resourcelocation); @@ -292,7 +365,7 @@ } else { - TextureAtlasSprite textureatlassprite = this.field_110574_e.get(p_174942_1_); + TextureAtlasSprite textureatlassprite = this.field_110574_e.get(p_174942_1_.toString()); if (textureatlassprite == null) { @@ -318,4 +391,52 @@ { return this.field_94249_f; } + + //=================================================================================================== + // Forge Start + //=================================================================================================== + + private final java.util.Deque loadingSprites = new java.util.ArrayDeque<>(); + private final java.util.Set loadedSprites = new java.util.HashSet<>(); + + /** + * Grabs the registered entry for the specified name, returning null if there was not a entry. + * Opposed to registerIcon, this will not instantiate the entry, useful to test if a mapping exists. + * + * @param name The name of the entry to find + * @return The registered entry, null if nothing was registered. + */ + @Nullable + public TextureAtlasSprite getTextureExtry(String name) + { + return field_110574_e.get(name); + } + + /** + * Adds a texture registry entry to this map for the specified name if one does not already exist. + * Returns false if the map already contains a entry for the specified name. + * + * @param entry Entry instance + * @return True if the entry was added to the map, false otherwise. + */ + public boolean setTextureEntry(TextureAtlasSprite entry) + { + String name = entry.func_94215_i(); + if (!field_110574_e.containsKey(name)) + { + field_110574_e.put(name, entry); + return true; + } + return false; + } + + public String getBasePath() + { + return field_94254_c; + } + + public int getMipmapLevels() + { + return field_147636_j; + } }