package net.minecraft.client.resources; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.Maps; import com.mojang.authlib.GameProfile; import com.mojang.authlib.minecraft.InsecureTextureException; import com.mojang.authlib.minecraft.MinecraftProfileTexture; import com.mojang.authlib.minecraft.MinecraftSessionService; import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import java.awt.image.BufferedImage; import java.io.File; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IImageBuffer; import net.minecraft.client.renderer.ImageBufferDownload; import net.minecraft.client.renderer.ThreadDownloadImageData; import net.minecraft.client.renderer.texture.ITextureObject; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.util.ResourceLocation; @SideOnly(Side.CLIENT) public class SkinManager { public static final ResourceLocation DEFAULT_SKIN = new ResourceLocation("textures/entity/steve.png"); private static final ExecutorService THREAD_POOL = new ThreadPoolExecutor(0, 2, 1L, TimeUnit.MINUTES, new LinkedBlockingQueue()); private final TextureManager textureManager; private final File skinCacheDir; private final MinecraftSessionService sessionService; private final LoadingCache skinCacheLoader; private static final String __OBFID = "CL_00001830"; public SkinManager(TextureManager textureManagerInstance, File skinCacheDirectory, MinecraftSessionService sessionService) { this.textureManager = textureManagerInstance; this.skinCacheDir = skinCacheDirectory; this.sessionService = sessionService; this.skinCacheLoader = CacheBuilder.newBuilder().expireAfterAccess(15L, TimeUnit.SECONDS).build(new CacheLoader() { private static final String __OBFID = "CL_00001829"; public Map func_152786_a(GameProfile p_152786_1_) { return Minecraft.getMinecraft().getSessionService().getTextures(p_152786_1_, false); } public Object load(Object p_load_1_) { return this.func_152786_a((GameProfile)p_load_1_); } }); } /** * Used in the Skull renderer to fetch a skin. May download the skin if it's not in the cache */ public ResourceLocation loadSkin(MinecraftProfileTexture p_152792_1_, Type p_152792_2_) { return this.loadSkin(p_152792_1_, p_152792_2_, (SkinManager.SkinAvailableCallback)null); } /** * May download the skin if its not in the cache, can be passed a SkinManager#SkinAvailableCallback for handling */ public ResourceLocation loadSkin(MinecraftProfileTexture p_152789_1_, final Type p_152789_2_, final SkinManager.SkinAvailableCallback p_152789_3_) { final ResourceLocation resourcelocation = new ResourceLocation("skins/" + p_152789_1_.getHash()); ITextureObject itextureobject = this.textureManager.getTexture(resourcelocation); if (itextureobject != null) { if (p_152789_3_ != null) { p_152789_3_.onSkinAvailable(p_152789_2_, resourcelocation); } } else { File file1 = new File(this.skinCacheDir, p_152789_1_.getHash().substring(0, 2)); File file2 = new File(file1, p_152789_1_.getHash()); final ImageBufferDownload imagebufferdownload = p_152789_2_ == Type.SKIN ? new ImageBufferDownload() : null; ThreadDownloadImageData threaddownloadimagedata = new ThreadDownloadImageData(file2, p_152789_1_.getUrl(), DEFAULT_SKIN, new IImageBuffer() { private static final String __OBFID = "CL_00001828"; public BufferedImage parseUserSkin(BufferedImage p_78432_1_) { if (imagebufferdownload != null) { p_78432_1_ = imagebufferdownload.parseUserSkin(p_78432_1_); } return p_78432_1_; } public void func_152634_a() { if (imagebufferdownload != null) { imagebufferdownload.func_152634_a(); } if (p_152789_3_ != null) { p_152789_3_.onSkinAvailable(p_152789_2_, resourcelocation); } } }); this.textureManager.loadTexture(resourcelocation, threaddownloadimagedata); } return resourcelocation; } public void func_152790_a(final GameProfile p_152790_1_, final SkinManager.SkinAvailableCallback p_152790_2_, final boolean p_152790_3_) { THREAD_POOL.submit(new Runnable() { private static final String __OBFID = "CL_00001827"; public void run() { final HashMap hashmap = Maps.newHashMap(); try { hashmap.putAll(SkinManager.this.sessionService.getTextures(p_152790_1_, p_152790_3_)); } catch (InsecureTextureException insecuretextureexception) { ; } if (hashmap.isEmpty() && p_152790_1_.getId().equals(Minecraft.getMinecraft().getSession().getProfile().getId())) { hashmap.putAll(SkinManager.this.sessionService.getTextures(SkinManager.this.sessionService.fillProfileProperties(p_152790_1_, false), false)); } Minecraft.getMinecraft().addScheduledTask(new Runnable() { private static final String __OBFID = "CL_00001826"; public void run() { if (hashmap.containsKey(Type.SKIN)) { SkinManager.this.loadSkin((MinecraftProfileTexture)hashmap.get(Type.SKIN), Type.SKIN, p_152790_2_); } if (hashmap.containsKey(Type.CAPE)) { SkinManager.this.loadSkin((MinecraftProfileTexture)hashmap.get(Type.CAPE), Type.CAPE, p_152790_2_); } } }); } }); } public Map loadSkinFromCache(GameProfile p_152788_1_) { return (Map)this.skinCacheLoader.getUnchecked(p_152788_1_); } @SideOnly(Side.CLIENT) public interface SkinAvailableCallback { /** * Called when the skinmanager completes downloading part of a skin. May be called twice if the player has both * a skin and a cape. * * @param skinPart Either Type.SKIN or Type.CAPE */ void onSkinAvailable(Type skinPart, ResourceLocation skinLoc); } }