Files

190 lines
7.6 KiB
Java
Raw Permalink 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;
2020-01-24 16:56:26 +08:00
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
2016-12-25 17:05:30 +08:00
import customskinloader.forge.platform.IFMLPlatform;
import org.objectweb.asm.commons.Remapper;
2016-12-25 17:05:30 +08:00
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
2018-08-26 07:04:25 +08:00
public class TransformerManager {
2018-02-12 12:20:28 +08:00
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
2018-08-26 07:04:25 +08:00
public @interface TransformTarget {
2019-12-09 23:20:52 +08:00
String className();
2018-08-26 07:04:25 +08:00
String methodNameSrg() default "";
2020-01-24 16:56:26 +08:00
String[] methodNames() default {};
String desc() default "";
}
2018-08-26 07:04:25 +08:00
2020-01-24 16:56:26 +08:00
public interface IClassTransformer {
ClassNode transform(ClassNode cn);
2018-02-12 12:20:28 +08:00
}
2018-08-26 07:04:25 +08:00
public interface IMethodTransformer {
MethodNode transform(ClassNode cn, MethodNode mn);
2018-02-12 12:20:28 +08:00
}
2018-08-26 07:04:25 +08:00
public static boolean isDevelopmentEnvironment = false;
/** If true, match {@link TransformTarget#methodNames} if {@link TransformTarget#methodNameSrg} fails to match. */
public static boolean useDeobfName = false;
private final static Remapper remapper = IFMLPlatform.FMLPlatformInitializer.getPlatform().getRemapper();
public static String mapClassName(String name) {
return remapper.mapType(name);
}
public static String mapFieldName(String owner, String name, String desc) {
return remapper.mapFieldName(owner, name, desc);
}
2022-12-07 19:38:24 +08:00
public static String mapFieldDesc(String desc) {
return remapper.mapDesc(desc);
}
public static String mapMethodName(String owner, String name, String desc) {
return remapper.mapMethodName(owner, name, desc);
}
public static String mapMethodDesc(String desc) {
return remapper.mapMethodDesc(desc);
}
public static boolean checkClassName(String name, String deobfName) {
if (isDevelopmentEnvironment) {
return name.equals(deobfName);
} else {
return mapClassName(name).equals(deobfName);
}
}
2022-12-07 19:38:24 +08:00
public static boolean checkFieldName(String owner, String name, String desc, String srgName) {
if (isDevelopmentEnvironment) {
return mapFieldName(owner, srgName, desc).equals(name);
} else {
return mapFieldName(owner, name, desc).equals(srgName);
}
}
public static boolean checkFieldDesc(String desc, String deobfDesc) {
if (isDevelopmentEnvironment) {
return desc.equals(deobfDesc);
} else {
return mapFieldDesc(desc).equals(deobfDesc);
}
}
public static boolean checkMethodName(String owner, String name, String desc, String srgName) {
if (isDevelopmentEnvironment) {
return mapMethodName(owner, srgName, desc).equals(name);
} else {
return mapMethodName(owner, name, desc).equals(srgName);
}
}
2018-08-26 07:04:25 +08:00
public static boolean checkMethodDesc(String desc, String deobfDesc) {
if (isDevelopmentEnvironment) {
return desc.equals(deobfDesc);
} else {
return mapMethodDesc(desc).equals(deobfDesc);
}
2020-01-24 16:56:26 +08:00
}
public Map<String, IClassTransformer> classMap = new HashMap<>();
public Map<String, Map<Supplier<String>, IMethodTransformer>> srgMap = new HashMap<>();
public Map<String, Map<String, IMethodTransformer>> map = new HashMap<>();
2020-01-24 16:56:26 +08:00
public TransformerManager(IClassTransformer[] classTransformers, IMethodTransformer[] methodTransformers) {
for (IClassTransformer t : classTransformers) {
TransformTarget tt = this.getTransformTarget(t.getClass());
if (tt != null) {
addClassTransformer(tt.className(), t);
2018-02-12 12:20:28 +08:00
}
2020-01-24 16:56:26 +08:00
}
for (IMethodTransformer t : methodTransformers) {
TransformTarget tt = this.getTransformTarget(t.getClass());
if (tt != null) {
addMethodTransformer(tt, tt.className(), t);
}
}
}
private TransformTarget getTransformTarget(Class<?> cl) {
ForgeTweaker.logger.info("[CSL DEBUG] REGISTERING TRANSFORMER %s", cl.getName());
2020-01-24 16:56:26 +08:00
if (!cl.isAnnotationPresent(TransformTarget.class)) {
ForgeTweaker.logger.info("[CSL DEBUG] ERROR occurs while parsing Annotation");
2020-01-24 16:56:26 +08:00
return null;
}
return cl.getAnnotation(TransformTarget.class);
}
2019-12-09 23:20:52 +08:00
2020-01-24 16:56:26 +08:00
private void addClassTransformer(String className, IClassTransformer transformer) {
if (!classMap.containsKey(className)) {
classMap.put(className, transformer);
ForgeTweaker.logger.info("[CSL DEBUG] REGISTERING CLASS %s", className);
2018-02-12 12:20:28 +08:00
}
}
2018-08-26 07:04:25 +08:00
2019-12-09 23:10:27 +08:00
private void addMethodTransformer(TransformTarget target, String className, IMethodTransformer transformer) {
if (!srgMap.containsKey(className)) {
srgMap.put(className, new HashMap<>());
}
if (!target.methodNameSrg().equals("")) {
// FMLDeobfRemapper has not been setup when this line being reached.
Supplier<String> mappedMethod = () -> (isDevelopmentEnvironment ? mapMethodName(className.replace(".", "/"), target.methodNameSrg(), target.desc()) : target.methodNameSrg()) + target.desc();
srgMap.get(className).put(mappedMethod, transformer);
ForgeTweaker.logger.info("[CSL DEBUG] REGISTERING SRG METHOD %s::%s", className, target.methodNameSrg() + target.desc());
}
2019-12-09 23:10:27 +08:00
if (!map.containsKey(className))
map.put(className, new HashMap<>());
2018-08-26 07:04:25 +08:00
for (String methodName : target.methodNames()) {
2019-12-09 23:10:27 +08:00
map.get(className).put(methodName + target.desc(), transformer);
ForgeTweaker.logger.info("[CSL DEBUG] REGISTERING METHOD %s::%s", className, methodName + target.desc());
2018-02-12 12:20:28 +08:00
}
}
2018-08-26 07:04:25 +08:00
public ClassNode transform(ClassNode classNode, String className) {
IClassTransformer transformer = classMap.get(className);
2020-01-24 16:56:26 +08:00
if (transformer != null) {
try {
classNode = transformer.transform(classNode);
ForgeTweaker.logger.info("[CSL DEBUG] Successfully transformed class %s", className);
2020-01-24 16:56:26 +08:00
} catch (Exception e) {
ForgeTweaker.logger.warning("[CSL DEBUG] An error happened when transforming class %s", className);
ForgeTweaker.logger.warning(e);
2020-01-24 16:56:26 +08:00
}
}
return classNode;
}
2019-03-01 14:59:02 +08:00
public MethodNode transform(ClassNode classNode, MethodNode methodNode, String className, String methodName, String methodDesc) {
String methodTarget = methodName + methodDesc;
Map<Supplier<String>, IMethodTransformer> transSrgMap = srgMap.get(className);
IMethodTransformer transformer = transSrgMap == null ? null : transSrgMap.get(transSrgMap.keySet().stream().filter(s -> s.get().equals(methodTarget)).findFirst().orElse(null));
Map<String, IMethodTransformer> transMap = map.get(className);
if (useDeobfName && transMap != null && transformer == null) {
transformer = transMap.get(methodTarget);
}
if (transformer != null) {
2019-03-01 14:59:02 +08:00
try {
methodNode = transformer.transform(classNode, methodNode);
ForgeTweaker.logger.info("[CSL DEBUG] Successfully transformed method %s in class %s", methodName, className);
2019-03-01 14:59:02 +08:00
} catch (Exception e) {
ForgeTweaker.logger.warning("[CSL DEBUG] An error happened when transforming method %s in class %s", methodTarget, className);
ForgeTweaker.logger.warning(e);
2018-02-12 12:20:28 +08:00
}
}
2019-03-01 14:59:02 +08:00
return methodNode;
2018-02-12 12:20:28 +08:00
}
2016-12-25 17:05:30 +08:00
}