package net.minecraft.client.renderer.texture; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.Callable; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.StitcherException; import net.minecraft.client.resources.IResource; import net.minecraft.client.resources.IResourceManager; import net.minecraft.client.resources.data.AnimationMetadataSection; import net.minecraft.client.resources.data.TextureMetadataSection; import net.minecraft.crash.CrashReport; import net.minecraft.crash.CrashReportCategory; import net.minecraft.src.Config; import net.minecraft.src.ConnectedTextures; import net.minecraft.src.Reflector; import net.minecraft.src.TextureUtils; import net.minecraft.util.MathHelper; import net.minecraft.util.ReportedException; import net.minecraft.util.ResourceLocation; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class TextureMap extends AbstractTexture implements ITickableTextureObject { private static final Logger logger = LogManager.getLogger(); public static final ResourceLocation field_174945_f = new ResourceLocation("missingno"); public static final ResourceLocation locationBlocksTexture = new ResourceLocation("textures/atlas/blocks.png"); private final List listAnimatedSprites; private final Map mapRegisteredSprites; private final Map mapUploadedSprites; private final String basePath; private final IIconCreator field_174946_m; private int mipmapLevels; private final TextureAtlasSprite missingImage; private static final String __OBFID = "CL_00001058"; public TextureMap(String p_i46099_1_) { this(p_i46099_1_, (IIconCreator)null); } public TextureMap(String p_i46100_1_, IIconCreator p_i46100_2_) { this.listAnimatedSprites = Lists.newArrayList(); this.mapRegisteredSprites = Maps.newHashMap(); this.mapUploadedSprites = Maps.newHashMap(); this.missingImage = new TextureAtlasSprite("missingno"); this.basePath = p_i46100_1_; this.field_174946_m = p_i46100_2_; } private void initMissingImage() { int[] var1 = TextureUtil.missingTextureData; this.missingImage.setIconWidth(16); this.missingImage.setIconHeight(16); int[][] var2 = new int[this.mipmapLevels + 1][]; var2[0] = var1; this.missingImage.setFramesTextureData(Lists.newArrayList(new int[][][] {var2})); this.missingImage.setIndexInMap(0); } public void loadTexture(IResourceManager p_110551_1_) throws IOException { if (this.field_174946_m != null) { this.func_174943_a(p_110551_1_, this.field_174946_m); } } public void func_174943_a(IResourceManager p_174943_1_, IIconCreator p_174943_2_) { this.mapRegisteredSprites.clear(); p_174943_2_.func_177059_a(this); this.initMissingImage(); this.deleteGlTexture(); ConnectedTextures.updateIcons(this); this.loadTextureAtlas(p_174943_1_); } public void loadTextureAtlas(IResourceManager p_110571_1_) { int var2 = Minecraft.getGLMaximumTextureSize(); Stitcher var3 = new Stitcher(var2, var2, true, 0, this.mipmapLevels); this.mapUploadedSprites.clear(); this.listAnimatedSprites.clear(); int var4 = Integer.MAX_VALUE; Reflector.callVoid(Reflector.ForgeHooksClient_onTextureStitchedPre, new Object[] {this}); int var5 = 1 << this.mipmapLevels; Iterator var6 = this.mapRegisteredSprites.entrySet().iterator(); while (true) { while (var6.hasNext()) { Entry var25 = (Entry)var6.next(); TextureAtlasSprite var26 = (TextureAtlasSprite)var25.getValue(); ResourceLocation var27 = new ResourceLocation(var26.getIconName()); ResourceLocation var28 = this.completeResourceLocation(var27, 0); if (!var26.hasCustomLoader(p_110571_1_, var27)) { try { IResource var30 = p_110571_1_.getResource(var28); BufferedImage[] var31 = new BufferedImage[1 + this.mipmapLevels]; var31[0] = TextureUtil.func_177053_a(var30.getInputStream()); TextureMetadataSection var34 = (TextureMetadataSection)var30.getMetadata("texture"); if (var34 != null) { List var19 = var34.getListMipmaps(); int var36; if (!var19.isEmpty()) { int var38 = var31[0].getWidth(); var36 = var31[0].getHeight(); if (MathHelper.roundUpToPowerOfTwo(var38) != var38 || MathHelper.roundUpToPowerOfTwo(var36) != var36) { throw new RuntimeException("Unable to load extra miplevels, source-texture is not power of two"); } } Iterator var381 = var19.iterator(); while (var381.hasNext()) { var36 = ((Integer)var381.next()).intValue(); if (var36 > 0 && var36 < var31.length - 1 && var31[var36] == null) { ResourceLocation var17 = this.completeResourceLocation(var27, var36); try { var31[var36] = TextureUtil.func_177053_a(p_110571_1_.getResource(var17).getInputStream()); } catch (IOException var22) { logger.error("Unable to load miplevel {} from: {}", new Object[] {Integer.valueOf(var36), var17, var22}); } } } } AnimationMetadataSection var192 = (AnimationMetadataSection)var30.getMetadata("animation"); var26.func_180598_a(var31, var192); } catch (RuntimeException var23) { logger.error("Unable to parse metadata from " + var28, var23); continue; } catch (IOException var24) { logger.error("Using missing texture, unable to load " + var28 + ", " + var24.getClass().getName()); continue; } var4 = Math.min(var4, Math.min(var26.getIconWidth(), var26.getIconHeight())); int var301 = Math.min(Integer.lowestOneBit(var26.getIconWidth()), Integer.lowestOneBit(var26.getIconHeight())); if (var301 < var5) { logger.warn("Texture {} with size {}x{} limits mip level from {} to {}", new Object[] {var28, Integer.valueOf(var26.getIconWidth()), Integer.valueOf(var26.getIconHeight()), Integer.valueOf(MathHelper.calculateLogBaseTwo(var5)), Integer.valueOf(MathHelper.calculateLogBaseTwo(var301))}); var5 = var301; } var3.addSprite(var26); } else if (!var26.load(p_110571_1_, var27)) { var4 = Math.min(var4, Math.min(var26.getIconWidth(), var26.getIconHeight())); var3.addSprite(var26); } } int var251 = Math.min(var4, var5); int var261 = MathHelper.calculateLogBaseTwo(var251); if (var261 < 0) { var261 = 0; } if (var261 < this.mipmapLevels) { logger.info("{}: dropping miplevel from {} to {}, because of minimum power of two: {}", new Object[] {this.basePath, Integer.valueOf(this.mipmapLevels), Integer.valueOf(var261), Integer.valueOf(var251)}); this.mipmapLevels = var261; } Iterator var271 = this.mapRegisteredSprites.values().iterator(); while (var271.hasNext()) { final TextureAtlasSprite var281 = (TextureAtlasSprite)var271.next(); try { var281.generateMipmaps(this.mipmapLevels); } catch (Throwable var21) { CrashReport var311 = CrashReport.makeCrashReport(var21, "Applying mipmap"); CrashReportCategory var341 = var311.makeCategory("Sprite being mipmapped"); var341.addCrashSectionCallable("Sprite name", new Callable() { private static final String __OBFID = "CL_00001059"; public String call() { return var281.getIconName(); } }); var341.addCrashSectionCallable("Sprite size", new Callable() { private static final String __OBFID = "CL_00001060"; public String call() { return var281.getIconWidth() + " x " + var281.getIconHeight(); } }); var341.addCrashSectionCallable("Sprite frames", new Callable() { private static final String __OBFID = "CL_00001061"; public String call() { return var281.getFrameCount() + " frames"; } }); var341.addCrashSection("Mipmap levels", Integer.valueOf(this.mipmapLevels)); throw new ReportedException(var311); } } this.missingImage.generateMipmaps(this.mipmapLevels); var3.addSprite(this.missingImage); try { var3.doStitch(); } catch (StitcherException var20) { throw var20; } logger.info("Created: {}x{} {}-atlas", new Object[] {Integer.valueOf(var3.getCurrentWidth()), Integer.valueOf(var3.getCurrentHeight()), this.basePath}); TextureUtil.func_180600_a(this.getGlTextureId(), this.mipmapLevels, var3.getCurrentWidth(), var3.getCurrentHeight()); HashMap var282 = Maps.newHashMap(this.mapRegisteredSprites); Iterator var302 = var3.getStichSlots().iterator(); TextureAtlasSprite var312; while (var302.hasNext()) { var312 = (TextureAtlasSprite)var302.next(); String var342 = var312.getIconName(); var282.remove(var342); this.mapUploadedSprites.put(var342, var312); try { TextureUtil.uploadTextureMipmap(var312.getFrameTextureData(0), var312.getIconWidth(), var312.getIconHeight(), var312.getOriginX(), var312.getOriginY(), false, false); } catch (Throwable var191) { CrashReport var361 = CrashReport.makeCrashReport(var191, "Stitching texture atlas"); CrashReportCategory var382 = var361.makeCategory("Texture being stitched together"); var382.addCrashSection("Atlas path", this.basePath); var382.addCrashSection("Sprite", var312); throw new ReportedException(var361); } if (var312.hasAnimationMetadata()) { this.listAnimatedSprites.add(var312); } } var302 = var282.values().iterator(); while (var302.hasNext()) { var312 = (TextureAtlasSprite)var302.next(); var312.copyFrom(this.missingImage); } TextureUtil.func_177055_a(this.basePath.replaceAll("/", "_"), this.getGlTextureId(), this.mipmapLevels, var3.getCurrentWidth(), var3.getCurrentHeight()); Reflector.callVoid(Reflector.ForgeHooksClient_onTextureStitchedPost, new Object[] {this}); return; } } private ResourceLocation completeResourceLocation(ResourceLocation p_147634_1_, int p_147634_2_) { return this.isAbsoluteLocation(p_147634_1_) ? (p_147634_2_ == 0 ? new ResourceLocation(p_147634_1_.getResourceDomain(), p_147634_1_.getResourcePath() + ".png") : new ResourceLocation(p_147634_1_.getResourceDomain(), p_147634_1_.getResourcePath() + "mipmap" + p_147634_2_ + ".png")) : (p_147634_2_ == 0 ? new ResourceLocation(p_147634_1_.getResourceDomain(), String.format("%s/%s%s", new Object[] {this.basePath, p_147634_1_.getResourcePath(), ".png"})): new ResourceLocation(p_147634_1_.getResourceDomain(), String.format("%s/mipmaps/%s.%d%s", new Object[] {this.basePath, p_147634_1_.getResourcePath(), Integer.valueOf(p_147634_2_), ".png"}))); } public TextureAtlasSprite getAtlasSprite(String p_110572_1_) { TextureAtlasSprite var2 = (TextureAtlasSprite)this.mapUploadedSprites.get(p_110572_1_); if (var2 == null) { var2 = this.missingImage; } return var2; } public void updateAnimations() { TextureUtil.bindTexture(this.getGlTextureId()); Iterator var1 = this.listAnimatedSprites.iterator(); while (var1.hasNext()) { TextureAtlasSprite var2 = (TextureAtlasSprite)var1.next(); if (this.isTerrainAnimationActive(var2)) { var2.updateAnimation(); } } } public TextureAtlasSprite func_174942_a(ResourceLocation p_174942_1_) { if (p_174942_1_ == null) { throw new IllegalArgumentException("Location cannot be null!"); } else { TextureAtlasSprite var2 = (TextureAtlasSprite)this.mapRegisteredSprites.get(p_174942_1_.toString()); if (var2 == null && Reflector.ModLoader_getCustomAnimationLogic.exists()) { var2 = (TextureAtlasSprite)Reflector.call(Reflector.ModLoader_getCustomAnimationLogic, new Object[] {p_174942_1_}); } if (var2 == null) { var2 = TextureAtlasSprite.func_176604_a(p_174942_1_); this.mapRegisteredSprites.put(p_174942_1_.toString(), var2); if (var2 instanceof TextureAtlasSprite && var2.getIndexInMap() < 0) { var2.setIndexInMap(this.mapRegisteredSprites.size()); } } return var2; } } public void tick() { this.updateAnimations(); } public void setMipmapLevels(int p_147633_1_) { this.mipmapLevels = p_147633_1_; } public TextureAtlasSprite func_174944_f() { return this.missingImage; } public TextureAtlasSprite getTextureExtry(String name) { ResourceLocation loc = new ResourceLocation(name); return (TextureAtlasSprite)this.mapRegisteredSprites.get(loc.toString()); } public boolean setTextureEntry(String name, TextureAtlasSprite entry) { if (!this.mapRegisteredSprites.containsKey(name)) { this.mapRegisteredSprites.put(name, entry); if (entry.getIndexInMap() < 0) { entry.setIndexInMap(this.mapRegisteredSprites.size()); } return true; } else { return false; } } private boolean isAbsoluteLocation(ResourceLocation loc) { String path = loc.getResourcePath(); return this.isAbsoluteLocationPath(path); } private boolean isAbsoluteLocationPath(String resPath) { String path = resPath.toLowerCase(); return path.startsWith("mcpatcher/") || path.startsWith("optifine/"); } public TextureAtlasSprite getSpriteSafe(String name) { ResourceLocation loc = new ResourceLocation(name); return (TextureAtlasSprite)this.mapRegisteredSprites.get(loc.toString()); } private boolean isTerrainAnimationActive(TextureAtlasSprite ts) { return ts != TextureUtils.iconWaterStill && ts != TextureUtils.iconWaterFlow ? (ts != TextureUtils.iconLavaStill && ts != TextureUtils.iconLavaFlow ? (ts != TextureUtils.iconFireLayer0 && ts != TextureUtils.iconFireLayer1 ? (ts == TextureUtils.iconPortal ? Config.isAnimatedPortal() : Config.isAnimatedTerrain()) : Config.isAnimatedFire()) : Config.isAnimatedLava()) : Config.isAnimatedWater(); } public int getCountRegisteredSprites() { return this.mapRegisteredSprites.size(); } }