Files
MCCustomSkinLoader/Forge/source/customskinloader/forge/TransformerManager.java
T

100 lines
4.7 KiB
Java
Raw Normal View History

2016-12-25 17:05:30 +08:00
package customskinloader.forge;
2016-12-29 16:44:16 +08:00
import java.lang.annotation.ElementType;
2016-12-31 23:05:55 +08:00
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
2016-12-29 16:44:16 +08:00
import java.lang.annotation.Target;
2016-12-25 17:05:30 +08:00
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
2018-06-25 00:34:32 +08:00
import customskinloader.Logger;
2016-12-25 17:05:30 +08:00
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraftforge.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
2018-07-26 20:50:41 +08:00
import customskinloader.forge.transformer.*;
2018-06-25 00:56:47 +08:00
import customskinloader.forge.transformer.PlayerTabTransformer.ScoreObjectiveTransformer;
import customskinloader.forge.transformer.SkinManagerTransformer.*;
import customskinloader.forge.transformer.SpectatorMenuTransformer.PlayerMenuObjectTransformer;
2017-01-01 01:06:40 +08:00
2016-12-25 17:05:30 +08:00
public class TransformerManager implements IClassTransformer {
2018-06-25 00:56:47 +08:00
public static Logger logger = new Logger("CustomSkinLoader/ForgePlugin.log");
2018-02-12 12:20:28 +08:00
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TransformTarget{
2018-06-25 00:34:32 +08:00
String className();
String[] methodNames();
String desc();
2018-02-12 12:20:28 +08:00
}
public interface IMethodTransformer{
2018-06-25 00:34:32 +08:00
void transform(ClassNode cn,MethodNode mn);
2018-02-12 12:20:28 +08:00
}
private static final IMethodTransformer[] TRANFORMERS={
new InitTransformer(),
new LoadSkinTransformer(),
new LoadProfileTexturesTransformer(),
new LoadSkinFromCacheTransformer(),
new ScoreObjectiveTransformer(),
2018-07-26 20:50:41 +08:00
new PlayerMenuObjectTransformer(),
new FakeSkinManagerTransformer.InitTransformer()
};
2018-02-12 12:20:28 +08:00
private Map<String, Map<String, IMethodTransformer>> map;
public TransformerManager(){
map = new HashMap<String, Map<String, IMethodTransformer>>();
for(IMethodTransformer t:TRANFORMERS){
2018-06-25 00:34:32 +08:00
logger.info("[CSL DEBUG] REGISTERING TRANSFORMER %s" , t.getClass().getName());
2018-02-12 12:20:28 +08:00
if(!t.getClass().isAnnotationPresent(TransformTarget.class)){
2018-06-25 00:34:32 +08:00
logger.info("[CSL DEBUG] ERROR occurs while parsing Annotation.");
2018-02-12 12:20:28 +08:00
continue;
}
addMethodTransformer(t.getClass().getAnnotation(TransformTarget.class),t);
}
}
private void addMethodTransformer(TransformTarget target, IMethodTransformer transformer) {
if (!map.containsKey(target.className()))
map.put(target.className(), new HashMap<String, IMethodTransformer>());
for(String methodName:target.methodNames()){
map.get(target.className()).put(methodName + target.desc(), transformer);
2018-06-25 00:34:32 +08:00
logger.info("[CSL DEBUG] REGISTERING METHOD %s(%s)",target.className(),methodName + target.desc());
2018-02-12 12:20:28 +08:00
}
}
//From: https://github.com/RecursiveG/UniSkinMod/blob/1.9.4/src/main/java/org/devinprogress/uniskinmod/coremod/BaseAsmTransformer.java#L83-L114
@Override
public byte[] transform(String obfClassName, String className, byte[] bytes) {
if (!map.containsKey(className)) return bytes;
2018-06-25 00:34:32 +08:00
logger.info("[CSL DEBUG] CLASS %s will be transformed", className);
2018-02-12 12:20:28 +08:00
Map<String, IMethodTransformer> transMap = map.get(className);
ClassReader cr = new ClassReader(bytes);
ClassNode cn = new ClassNode();
cr.accept(cn, 0);
2016-12-25 17:05:30 +08:00
2018-02-12 12:20:28 +08:00
// NOTE: `map` = convert obfuscated name to srgName;
2018-06-25 00:34:32 +08:00
List<MethodNode> ml = new ArrayList<MethodNode>(cn.methods);
2018-02-12 12:20:28 +08:00
for (MethodNode mn : ml) {
String methodName = FMLDeobfuscatingRemapper.INSTANCE.mapMethodName(obfClassName, mn.name, mn.desc);
String methodDesc = FMLDeobfuscatingRemapper.INSTANCE.mapMethodDesc(mn.desc);
if (transMap.containsKey(methodName + methodDesc)) {
try {
2018-06-25 00:34:32 +08:00
logger.info("[CSL DEBUG] Transforming method %s in class %s(%s)", methodName + methodDesc, obfClassName, className);
2018-02-12 12:20:28 +08:00
transMap.get(methodName + methodDesc).transform(cn,mn);
2018-06-25 00:34:32 +08:00
logger.info("[CSL DEBUG] Successfully transformed method %s in class %s(%s)", methodName + methodDesc, obfClassName, className);
2018-02-12 12:20:28 +08:00
} catch (Exception e) {
2018-06-25 00:34:32 +08:00
logger.warning("[CSL DEBUG] An error happened when transforming method %s in class %s(%s). The whole class was not modified.", methodName + methodDesc, obfClassName, className);
2018-02-12 12:20:28 +08:00
e.printStackTrace();
return bytes;
}
}
}
2016-12-25 17:05:30 +08:00
2018-02-12 12:20:28 +08:00
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
cn.accept(cw);
return cw.toByteArray();
}
2016-12-25 17:05:30 +08:00
}