Skip to content

Commit

Permalink
Fix Cape+Cleanup useless files
Browse files Browse the repository at this point in the history
  • Loading branch information
HowardZHY authored Nov 16, 2022
1 parent 46250e8 commit bfaddf1
Show file tree
Hide file tree
Showing 59 changed files with 5,213 additions and 0 deletions.
233 changes: 233 additions & 0 deletions src/main/java/customskinloader/CustomSkinLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
package customskinloader;

import java.io.File;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

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 customskinloader.config.Config;
import customskinloader.config.SkinSiteProfile;
import customskinloader.loader.ProfileLoader;
import customskinloader.profile.DynamicSkullManager;
import customskinloader.profile.ModelManager0;
import customskinloader.profile.ProfileCache;
import customskinloader.profile.UserProfile;
import customskinloader.utils.MinecraftUtil;

/**
* Custom skin loader mod for Minecraft.
*
* @author (C) Jeremy Lam [JLChnToZ] 2013-2014 & Alexander Xia [xfl03] 2014-2022
* @version @MOD_FULL_VERSION@
*/
public class CustomSkinLoader {
public static final String CustomSkinLoader_VERSION = "14.14-LF";
public static final String CustomSkinLoader_FULL_VERSION = "14.14-LF";
public static final int CustomSkinLoader_BUILD_NUMBER = 0;

public static final File
DATA_DIR = new File(MinecraftUtil.getMinecraftDataDir(), "CustomSkinLoader"),
LOG_FILE = new File(DATA_DIR, "CustomSkinLoader.log"),
CONFIG_FILE = new File(DATA_DIR, "CustomSkinLoader.json");

public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public static final Logger logger = initLogger();
public static final Config config = Config.loadConfig0();

private static final ProfileCache profileCache = new ProfileCache();
private static final DynamicSkullManager dynamicSkullManager = new DynamicSkullManager();

private static final ExecutorService THREAD_POOL = new ThreadPoolExecutor(config.threadPoolSize, config.threadPoolSize, 1L, TimeUnit.MINUTES, new LinkedBlockingQueue<>());

//Correct thread name in thread pool
private static final ThreadFactory defaultFactory = Executors.defaultThreadFactory();
private static final ThreadFactory customFactory = r -> {
Thread t = defaultFactory.newThread(r);
if (r instanceof Thread) {
t.setName(((Thread) r).getName());
}
return t;
};
//Thread pool will discard the oldest task when queue reaches 333 tasks
private static final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
config.threadPoolSize, config.threadPoolSize, 1L, TimeUnit.MINUTES,
new LinkedBlockingQueue<>(333), customFactory, new ThreadPoolExecutor.DiscardOldestPolicy()
);

public static void loadProfileTextures(Runnable runnable) {
THREAD_POOL.execute(runnable);
}

public static void loadProfileLazily(GameProfile gameProfile, Consumer<Map<MinecraftProfileTexture.Type, MinecraftProfileTexture>> consumer) {
String username = gameProfile.getName();
String credential = MinecraftUtil.getCredential(gameProfile);
// Fix: http://hopper.minecraft.net/crashes/minecraft/MCX-2773713
if (username == null) {
logger.warning("Could not load profile: username is null.");
consumer.accept(Maps.newHashMap());
return;
}
String tempName = Thread.currentThread().getName();
Thread.currentThread().setName(username); // Change Thread Name
if (profileCache.isLoading(credential)) {
profileCache.putLoader(credential, consumer);
Thread.currentThread().setName(tempName);
return;
}
consumer.accept(loadProfile(gameProfile));
Thread.currentThread().setName(tempName);
profileCache.getLastLoader(credential).ifPresent(c -> loadProfileLazily(gameProfile, c));
}

//For User Skin
public static Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> loadProfile(GameProfile gameProfile) {
String credential = MinecraftUtil.getCredential(gameProfile);
UserProfile profile;
if (profileCache.isReady(credential)) {
logger.info("Cached profile will be used.");
profile = profileCache.getProfile(credential);
if (profile == null) {
logger.warning("(Cached Profile is empty!) Expiry: " + profileCache.getExpiry(credential));
if (profileCache.isExpired(credential)) { // force load
profile = loadProfile0(gameProfile, false);
}
} else {
logger.info(profile.toString(profileCache.getExpiry(credential)));
}
} else {
profileCache.setLoading(credential, true);
profile = loadProfile0(gameProfile, false);
}
return ModelManager0.fromUserProfile(profile);
}

//Core
public static UserProfile loadProfile0(GameProfile gameProfile, boolean isSkull) {
String username = gameProfile.getName();
String credential = MinecraftUtil.getCredential(gameProfile);

profileCache.setLoading(credential, true);
logger.info("Loading " + username + "'s profile.");
if (config.loadlist == null || config.loadlist.isEmpty()) {
logger.info("LoadList is Empty.");
return null;
}

UserProfile profile0 = new UserProfile();
for (int i = 0; i < config.loadlist.size(); i++) {
SkinSiteProfile ssp = config.loadlist.get(i);
logger.info((i + 1) + "/" + config.loadlist.size() + " Try to load profile from '" + ssp.name + "'.");
if (ssp.type == null) {
logger.info("The type of '" + ssp.name + "' is null.");
continue;
}
ProfileLoader.IProfileLoader loader = ProfileLoader.LOADERS.get(ssp.type.toLowerCase());
if (loader == null) {
logger.info("Type '" + ssp.type + "' is not defined.");
continue;
}
UserProfile profile = null;
try {
profile = loader.loadProfile(ssp, gameProfile);
} catch (Exception e) {
logger.warning("Exception occurs while loading.");
logger.warning(e);
if (e.getCause() != null) {
logger.warning("Caused By:");
logger.warning(e.getCause());
}
}
if (profile == null) {
continue;
}
profile0.mix(profile);
if (isSkull && !profile0.hasSkinUrl()) {
continue;
}
if (!config.forceLoadAllTextures) {
break;
}
if (profile0.isFull()) {
break;
}
}
if (!profile0.isEmpty()) {
logger.info(username + "'s profile loaded.");
if (!config.enableCape) {
profile0.capeUrl = null;
}
profileCache.updateCache(credential, profile0);
profileCache.setLoading(credential, false);
logger.info(profile0.toString(profileCache.getExpiry(credential)));
return profile0;
}
logger.info(username + "'s profile not found in load list.");

if (config.enableLocalProfileCache) {
UserProfile profile = profileCache.getLocalProfile(credential);
if (profile == null) {
logger.info(username + "'s LocalProfile not found.");
} else {
profileCache.updateCache(credential, profile, false);
profileCache.setLoading(credential, false);
logger.info(username + "'s LocalProfile will be used.");
logger.info(profile.toString(profileCache.getExpiry(credential)));
return profile;
}
}
profileCache.setLoading(credential, false);
return null;
}

//For Skull
public static Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> loadProfileFromCache(final GameProfile gameProfile) {
String username = gameProfile.getName();
String credential = MinecraftUtil.getCredential(gameProfile);

//CustomSkinLoader needs username to load standard skin, if username not exist, only textures in NBT can be used
//Authlib 3.11.50 makes empty username to "\u0020"
if (username == null || username.isEmpty() || username.equals("\u0020") || credential == null) {
return dynamicSkullManager.getTexture(gameProfile);
}
if (config.forceUpdateSkull ? profileCache.isReady(credential) : profileCache.isExist(credential)) {
UserProfile profile = profileCache.getProfile(credential);
return ModelManager0.fromUserProfile(profile);
}
if (!profileCache.isLoading(credential)) {
profileCache.setLoading(credential, true);
Runnable loadThread = () -> {
String tempName = Thread.currentThread().getName();
Thread.currentThread().setName(username + "'s skull");
loadProfile0(gameProfile, true);//Load in thread
Thread.currentThread().setName(tempName);
};
if (config.forceUpdateSkull) {
new Thread(loadThread).start();
} else {
threadPool.execute(loadThread);
}
}
return Maps.newHashMap();
}

private static Logger initLogger() {
Logger logger = new Logger(LOG_FILE);
logger.info("CustomSkinLoader " + CustomSkinLoader_FULL_VERSION);
logger.info("DataDir: " + DATA_DIR.getAbsolutePath());
logger.info("Operating System: " + System.getProperty("os.name") + " (" + System.getProperty("os.arch") + ") version " + System.getProperty("os.version"));
logger.info("Java Version: " + System.getProperty("java.version") + ", " + System.getProperty("java.vendor"));
logger.info("Java VM Version: " + System.getProperty("java.vm.name") + " (" + System.getProperty("java.vm.info") + "), " + System.getProperty("java.vm.vendor"));
logger.info("Minecraft: " + MinecraftUtil.getMinecraftMainVersion() + "Legacy Fabric");
return logger;
}
}
106 changes: 106 additions & 0 deletions src/main/java/customskinloader/Logger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package customskinloader;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

@SuppressWarnings("ResultOfMethodCallIgnored")
public class Logger {
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public enum Level{
DEBUG("DEBUG",false),
INFO("INFO",true),
WARNING("WARNING",true);


String name;
boolean display;
Level(String name,boolean display){
this.name=name;
this.display=display;
}
public String getName(){
return name;
}
public boolean display(){
return display;
}
}
private BufferedWriter writer=null;
public Logger(){
//Logger isn't created.
}
public Logger(String logFile) {
this(new File(logFile));
}
public Logger(File logFile){
try {
if(!logFile.getParentFile().exists()){
logFile.getParentFile().mkdirs();
}
if(!logFile.exists())
logFile.createNewFile();

writer = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(logFile), "UTF-8"));

System.out.println("Log Path: " + logFile.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
}
}
public void close(){
if(writer!=null){
try {
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

public void log(Level level,String msg){
if(!level.display()&&writer==null)
return;
String sb = String.format("[%s %s] %s", Thread.currentThread().getName(), level.getName(), msg);
if(level.display())
System.out.println(sb);
if(writer==null)
return;
try {
String sb2 = String.format("[%s] %s\r\n", DATE_FORMAT.format(new Date()), sb);
writer.write(sb2);
writer.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
public void debug(String msg){
log(Level.DEBUG,msg);
}
public void debug(String format, Object... objs) {
debug(String.format(format, objs));
}
public void info(String msg){
log(Level.INFO,msg);
}
public void info(String format, Object... objs){
info(String.format(format, objs));
}
public void warning(String msg){
log(Level.WARNING,msg);
}
public void warning(String format, Object... objs){
warning(String.format(format, objs));
}
public void warning(Throwable e){
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
log(Level.WARNING,"Exception: "+sw.toString());
}
}
Loading

0 comments on commit bfaddf1

Please sign in to comment.