Files

160 lines
6.9 KiB
Java
Raw Permalink Normal View History

2016-09-10 21:00:53 +08:00
package customskinloader.profile;
import java.io.File;
2018-06-25 00:34:32 +08:00
import java.util.*;
2020-03-26 10:22:20 +08:00
import java.util.concurrent.ConcurrentHashMap;
2016-09-10 21:00:53 +08:00
2018-06-25 00:34:32 +08:00
import com.google.common.collect.Lists;
2016-09-10 21:00:53 +08:00
import org.apache.commons.codec.Charsets;
import org.apache.commons.codec.binary.Base64;
2016-11-19 19:35:17 +08:00
import org.apache.commons.io.FileUtils;
2016-09-10 21:00:53 +08:00
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;
2016-11-06 12:00:36 +08:00
import customskinloader.utils.HttpRequestUtil;
import customskinloader.utils.HttpRequestUtil.HttpRequest;
import customskinloader.utils.HttpRequestUtil.HttpResponce;
2016-09-10 21:00:53 +08:00
import customskinloader.utils.HttpTextureUtil;
import customskinloader.utils.HttpUtil0;
public class DynamicSkullManager {
2018-02-12 12:20:28 +08:00
public static class SkullTexture{
public Map<Type,MinecraftProfileTexture> textures;
public String index;//Index File
public ArrayList<String> skins;
public int interval;
public boolean fromZero;
//For program
public long startTime;
public int period;
}
2020-03-26 10:22:20 +08:00
private Map<GameProfile, SkullTexture> dynamicTextures = new ConcurrentHashMap<>();
private Map<GameProfile, Map<Type, MinecraftProfileTexture>> staticTextures = new ConcurrentHashMap<>();
2018-02-12 12:20:28 +08:00
private List<GameProfile> loadingList=new ArrayList<GameProfile>();
private void parseGameProfile(GameProfile profile){
2018-06-25 00:34:32 +08:00
Property textureProperty = Iterables.getFirst(profile.getProperties().get("textures"), null);
2018-02-12 12:20:28 +08:00
if (textureProperty==null){
2018-06-25 00:34:32 +08:00
staticTextures.put(profile, Maps.<Type, MinecraftProfileTexture>newHashMap());
2018-02-12 12:20:28 +08:00
return;
}
String value=textureProperty.getValue();
if(StringUtils.isBlank(value)){
2018-06-25 00:34:32 +08:00
staticTextures.put(profile, Maps.<Type, MinecraftProfileTexture>newHashMap());
2018-02-12 12:20:28 +08:00
return;
}
2018-06-25 00:34:32 +08:00
@SuppressWarnings("deprecation") String json = new String(Base64.decodeBase64(value), Charsets.UTF_8);
2018-02-12 12:20:28 +08:00
Gson gson=new GsonBuilder().registerTypeAdapter(UUID.class,new UUIDTypeAdapter()).create();
SkullTexture result=gson.fromJson(json,SkullTexture.class);
if(result==null){
2018-06-25 00:34:32 +08:00
staticTextures.put(profile, Maps.<Type, MinecraftProfileTexture>newHashMap());
2018-02-12 12:20:28 +08:00
return;
}
2018-06-25 00:34:32 +08:00
staticTextures.put(profile, (result.textures==null || !result.textures.containsKey(Type.SKIN)) ?
Maps.<Type, MinecraftProfileTexture>newHashMap() : parseTextures(result.textures));
2018-02-12 12:20:28 +08:00
if(StringUtils.isNotEmpty(result.index)){
File indexFile=new File(CustomSkinLoader.DATA_DIR,result.index);
try{
2018-06-25 00:34:32 +08:00
String index=FileUtils.readFileToString(indexFile, "UTF-8");
2018-02-12 12:20:28 +08:00
if(StringUtils.isNotEmpty(index)){
2018-06-25 00:34:32 +08:00
String[] skins = CustomSkinLoader.GSON.fromJson(index, String[].class);
if(skins != null && skins.length != 0)
result.skins = Lists.newArrayList(skins);
2018-02-12 12:20:28 +08:00
}
}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;i<result.skins.size();i++){//check and cache skins
String skin=result.skins.get(i);
if(HttpUtil0.isLocal(skin)){
//Local Skin
File skinFile=new File(CustomSkinLoader.DATA_DIR,skin);
if(skinFile.isFile()&&skinFile.length()>0){
//Skin found
String fakeUrl=HttpTextureUtil.getLocalFakeUrl(skin);
result.skins.set(i, fakeUrl);
}else{
//Could not find skin
result.skins.remove(i--);
}
}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--);
}
}
}
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<Type, MinecraftProfileTexture> parseTextures(Map<Type, MinecraftProfileTexture> 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())
2018-06-25 00:34:32 +08:00
return Maps.newHashMap();
2018-02-12 12:20:28 +08:00
textures.put(Type.SKIN, ModelManager0.getProfileTexture(HttpTextureUtil.getLocalFakeUrl(skinUrl), null));
return textures;
}
2016-11-19 19:35:17 +08:00
2018-02-12 12:20:28 +08:00
public Map<Type,MinecraftProfileTexture> getTexture(final GameProfile profile){
if(staticTextures.get(profile)!=null)
return staticTextures.get(profile);
if(loadingList.contains(profile))
2018-06-25 00:34:32 +08:00
return Maps.newHashMap();
2018-02-12 12:20:28 +08:00
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<Type,MinecraftProfileTexture> 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();
2018-06-25 00:34:32 +08:00
return Maps.newHashMap();
2018-02-12 12:20:28 +08:00
}
2016-09-10 21:00:53 +08:00
}