package customskinloader.profile; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import org.apache.commons.codec.Charsets; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.mojang.authlib.GameProfile; import com.mojang.authlib.minecraft.MinecraftProfileTexture; import com.mojang.authlib.minecraft.MinecraftProfileTexture.Type; import com.mojang.authlib.properties.Property; import com.mojang.util.UUIDTypeAdapter; import customskinloader.CustomSkinLoader; import customskinloader.utils.HttpRequestUtil; import customskinloader.utils.HttpRequestUtil.HttpRequest; import customskinloader.utils.HttpRequestUtil.HttpResponce; import customskinloader.utils.HttpTextureUtil; import customskinloader.utils.HttpUtil0; public class DynamicSkullManager { public static class SkullTexture{ public Map textures; public String index;//Index File public ArrayList skins; public int interval; public boolean fromZero; //For program public long startTime; public int period; } private Map dynamicTextures=new HashMap(); private Map> staticTextures=new HashMap>(); private List loadingList=new ArrayList(); private void parseGameProfile(GameProfile profile){ Property textureProperty=(Property)Iterables.getFirst(profile.getProperties().get("textures"), null); if (textureProperty==null){ staticTextures.put(profile, new HashMap()); return; } String value=textureProperty.getValue(); if(StringUtils.isBlank(value)){ staticTextures.put(profile, new HashMap()); return; } String json=new String(Base64.decodeBase64(value),Charsets.UTF_8); Gson gson=new GsonBuilder().registerTypeAdapter(UUID.class,new UUIDTypeAdapter()).create(); SkullTexture result=gson.fromJson(json,SkullTexture.class); if(result==null){ staticTextures.put(profile, new HashMap()); return; } staticTextures.put(profile, (result.textures==null||!result.textures.containsKey(Type.SKIN))?new HashMap():parseTextures(result.textures)); if(StringUtils.isNotEmpty(result.index)){ File indexFile=new File(CustomSkinLoader.DATA_DIR,result.index); try{ String index=FileUtils.readFileToString(indexFile, Charsets.UTF_8); if(StringUtils.isNotEmpty(index)){ ArrayList skins=CustomSkinLoader.GSON.fromJson(index, ArrayList.class); if(skins!=null&&!skins.isEmpty()) result.skins=skins; } }catch(Exception e){ CustomSkinLoader.logger.warning("Exception occurs while parsing index file: "+e.toString()); } } if(!CustomSkinLoader.config.enableDynamicSkull||result.skins==null||result.skins.isEmpty()) return; CustomSkinLoader.logger.info("Try to load Dynamic Skull: "+json); for(int i=0;i0){ //Skin found String fakeUrl=HttpTextureUtil.getLocalFakeUrl(skin); result.skins.set(i, fakeUrl); }else{ //Could not find skin result.skins.remove(i--); continue; } }else{ //Online Skin HttpResponce responce=HttpRequestUtil.makeHttpRequest(new HttpRequest(skin).setCacheFile(HttpTextureUtil.getCacheFile(FilenameUtils.getBaseName(skin))).setCacheTime(0).setLoadContent(false)); if(!responce.success){ //Could not load skin result.skins.remove(i--); continue; } } } if(result.skins.isEmpty()){//Nothing loaded CustomSkinLoader.logger.info("Failed: Nothing loaded."); return; } result.interval=Math.max(result.interval, 50); if(result.fromZero) result.startTime=System.currentTimeMillis(); result.period=result.interval*result.skins.size(); CustomSkinLoader.logger.info("Successfully loaded Dynamic Skull: "+new Gson().toJson(result)); dynamicTextures.put(profile, result); staticTextures.remove(profile); } //Support local skin for skull public Map parseTextures(Map textures) { MinecraftProfileTexture skin=textures.get(Type.SKIN); String skinUrl=skin.getUrl(); if(!HttpUtil0.isLocal(skinUrl)) return textures; File skinFile=new File(CustomSkinLoader.DATA_DIR,skinUrl); if(!skinFile.isFile()) return new HashMap(); textures.put(Type.SKIN, ModelManager0.getProfileTexture(HttpTextureUtil.getLocalFakeUrl(skinUrl), null)); return textures; } public Map getTexture(final GameProfile profile){ if(staticTextures.get(profile)!=null) return staticTextures.get(profile); if(loadingList.contains(profile)) return new HashMap(); if(dynamicTextures.containsKey(profile)){ SkullTexture texture=dynamicTextures.get(profile); long time=System.currentTimeMillis()-texture.startTime; int index=(int)Math.floor((time%texture.period)/texture.interval); Map map=Maps.newHashMap(); map.put(Type.SKIN, ModelManager0.getProfileTexture(texture.skins.get(index), null)); return map; } loadingList.add(profile); Thread loadThread=new Thread(){ public void run(){ parseGameProfile(profile);//Load in thread loadingList.remove(profile); } }; loadThread.setName("Skull "+profile.hashCode()); loadThread.start(); return new HashMap(); } }