Try to support 1.13 forge

This commit is contained in:
xfl03 committed 2019-03-01 14:59:02 +08:00
1 parent 7bbfd19bfd
commit 4cb1e348bb
12 files changed
+177 -112

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
{
"transformers": "transformers.js"
}
+19
View File
@@ -0,0 +1,19 @@
modLoader="javafml"
loaderVersion="[25,)"
issueTrackerURL="https://github.com/xfl03/MCCustomSkinLoader/issues"
displayURL="https://github.com/xfl03/MCCustomSkinLoader"
credits="GPLv3"
authors=["xfl03", "JLChnToZ"]
[[mods]]
modId="customskinloader"
version="${modFullVersion}"
displayName="CustomSkinLoader"
description='''
Custom Skin Loader for Minecraft
'''
[[dependencies.customskinloader]]
modId="forge"
mandatory=true
versionRange="[25,)"
ordering="NONE"
side="CLIENT"
+2 -1
View File
@@ -6,6 +6,7 @@
"version": "${modFullVersion}",
"url": "https://github.com/xfl03/MCCustomSkinLoader",
"authorList": ["xfl03", "JLChnToZ"],
"credits": "GPLv3"
"credits": "GPLv3",
"clientSideOnly": true
}
]
+35
View File
@@ -0,0 +1,35 @@
var JSAPI = Java.type('customskinloader.forge.loader.ModLauncher');
function f(cn) {
return JSAPI.instance().transform(cn);
}
function initializeCoreMod() {
return {
'SkinManagerTransformer': {
'target': {
'type': 'CLASS',
'name': 'net/minecraft/client/resources/SkinManager'
},
'transformer': function(cn) {
return f(cn);
}
},
'PlayerTabTransformer': {
'target': {
'type': 'CLASS',
'name': 'net/minecraft/client/gui/GuiPlayerTabOverlay'
},
'transformer': function(cn) {
return f(cn);
}
},
'FakeSkinManagerTransformer': {
'target': {
'type': 'CLASS',
'name': 'customskinloader/fake/FakeSkinManager'
},
'transformer': function(cn) {
return f(cn);
}
}
};
}
@@ -10,12 +10,7 @@ public class ForgePlugin implements IFMLLoadingPlugin {
@Override
public String[] getASMTransformerClass() {
try {
Class.forName("cpw.mods.modlauncher.api.ITransformer");
return new String[]{"customskinloader.forge.transformer.ModLauncher"};//ModLauncher
} catch (ClassNotFoundException ignored) {
return new String[]{"customskinloader.forge.transformer.LaunchWrapper"};//LaunchWrapper
}
return new String[]{"customskinloader.forge.loader.LaunchWrapper"};//LaunchWrapper
}
@Override
@@ -10,13 +10,7 @@ import java.util.*;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import net.minecraftforge.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
import customskinloader.Logger;
import customskinloader.forge.transformer.*;
import customskinloader.forge.transformer.PlayerTabTransformer.ScoreObjectiveTransformer;
import customskinloader.forge.transformer.SkinManagerTransformer.*;
import customskinloader.forge.transformer.SpectatorMenuTransformer.PlayerMenuObjectTransformer;
public class TransformerManager {
public static Logger logger = new Logger(new File("./CustomSkinLoader/ForgePlugin.log"));
@@ -35,20 +29,11 @@ public class TransformerManager {
void transform(ClassNode cn, MethodNode mn);
}
private static final IMethodTransformer[] TRANFORMERS = {
new InitTransformer(),
new LoadSkinTransformer(),
new LoadProfileTexturesTransformer(),
new LoadSkinFromCacheTransformer(),
new ScoreObjectiveTransformer(),
new PlayerMenuObjectTransformer(),
new FakeSkinManagerTransformer.InitTransformer()
};
public Map<String, Map<String, IMethodTransformer>> map;
public TransformerManager() {
public TransformerManager(IMethodTransformer... transformers) {
map = new HashMap<String, Map<String, IMethodTransformer>>();
for (IMethodTransformer t : TRANFORMERS) {
for (IMethodTransformer t : transformers) {
logger.info("[CSL DEBUG] REGISTERING TRANSFORMER %s", t.getClass().getName());
if (!t.getClass().isAnnotationPresent(TransformTarget.class)) {
logger.info("[CSL DEBUG] ERROR occurs while parsing Annotation.");
@@ -67,32 +52,18 @@ public class TransformerManager {
}
}
public ClassNode transform(ClassNode classNode) {
String obfClassName = classNode.name;
String className = FMLDeobfuscatingRemapper.INSTANCE.map(obfClassName);
return transform(classNode, className, obfClassName);
}
public ClassNode transform(ClassNode classNode, String className, String obfClassName) {
logger.info("[CSL DEBUG] CLASS %s will be transformed", className);
public MethodNode transform(ClassNode classNode, MethodNode methodNode, String className, String methodName, String methodDesc) {
Map<String, IMethodTransformer> transMap = map.get(className);
// NOTE: `map` = convert obfuscated name to srgName;
List<MethodNode> ml = new ArrayList<MethodNode>(classNode.methods);
for (MethodNode mn : ml) {
String methodName = FMLDeobfuscatingRemapper.INSTANCE.mapMethodName(obfClassName, mn.name, mn.desc);
String methodDesc = FMLDeobfuscatingRemapper.INSTANCE.mapMethodDesc(mn.desc);
String methodTarget = methodName + methodDesc;
if (transMap.containsKey(methodTarget)) {
try {
transMap.get(methodTarget).transform(classNode, mn);
logger.info("[CSL DEBUG] Successfully transformed method %s in class %s", methodName, className);
} catch (Exception e) {
logger.warning("[CSL DEBUG] An error happened when transforming method %s in class %s.", methodTarget, className);
logger.warning(e);
}
String methodTarget = methodName + methodDesc;
if (transMap.containsKey(methodTarget)) {
try {
transMap.get(methodTarget).transform(classNode, methodNode);
logger.info("[CSL DEBUG] Successfully transformed method %s in class %s", methodName, className);
} catch (Exception e) {
logger.warning("[CSL DEBUG] An error happened when transforming method %s in class %s.", methodTarget, className);
logger.warning(e);
}
}
return classNode;
return methodNode;
}
}
@@ -0,0 +1,50 @@
package customskinloader.forge.loader;
import customskinloader.forge.TransformerManager;
import customskinloader.forge.transformer.PlayerTabTransformer;
import customskinloader.forge.transformer.SkinManagerTransformer;
import customskinloader.forge.transformer.SpectatorMenuTransformer;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraftforge.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
//LaunchWrapper for 1.13-
public class LaunchWrapper implements IClassTransformer {
private static final TransformerManager.IMethodTransformer[] TRANFORMERS = {
new SkinManagerTransformer.InitTransformer(),
new SkinManagerTransformer.LoadSkinTransformer(),
new SkinManagerTransformer.LoadProfileTexturesTransformer(),
new SkinManagerTransformer.LoadSkinFromCacheTransformer(),
new PlayerTabTransformer.ScoreObjectiveTransformer(),
new SpectatorMenuTransformer.PlayerMenuObjectTransformer()
};
private TransformerManager transformerManager = new TransformerManager(TRANFORMERS);
//From: https://github.com/RecursiveG/UniSkinMod/blob/1.9.4/src/main/java/org/devinprogress/uniskinmod/coremod/BaseAsmTransformer.java#L83-L114
public byte[] transform(String obfClassName, String className, byte[] bytes) {
if (!transformerManager.map.containsKey(className)) return bytes;//Check if should be transformed
//Parse bytes to ClassNode
ClassReader cr = new ClassReader(bytes);
ClassNode cn = new ClassNode();
cr.accept(cn, 0);
//Transform ClassNode
for (MethodNode mn : cn.methods) {
String methodName = FMLDeobfuscatingRemapper.INSTANCE.mapMethodName(obfClassName, mn.name, mn.desc);
String methodDesc = FMLDeobfuscatingRemapper.INSTANCE.mapMethodDesc(mn.desc);
transformerManager.transform(cn, mn, className, methodName, methodDesc);
}
//Parse Class Node to bytes
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
cn.accept(cw);
return cw.toByteArray();
}
}
@@ -0,0 +1,45 @@
package customskinloader.forge.loader;
import customskinloader.forge.TransformerManager;
import customskinloader.forge.transformer.FakeSkinManagerTransformer;
import customskinloader.forge.transformer.PlayerTabTransformer;
import customskinloader.forge.transformer.SkinManagerTransformer;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
//ModLauncher for 1.13+
public class ModLauncher {
private static final TransformerManager.IMethodTransformer[] TRANFORMERS = {
new SkinManagerTransformer.InitTransformer(),
new SkinManagerTransformer.LoadSkinTransformer(),
new SkinManagerTransformer.LoadProfileTexturesTransformer(),
new SkinManagerTransformer.LoadSkinFromCacheTransformer(),
new PlayerTabTransformer.ScoreObjectiveTransformer(),
new FakeSkinManagerTransformer.InitTransformer()
};
private TransformerManager transformerManager = new TransformerManager(TRANFORMERS);
public ClassNode transform(ClassNode input) {
for (MethodNode mn : input.methods) {
transformerManager.transform(input, mn, input.name, mn.name, mn.desc);
}
return input;
}
//Singleton
private volatile static ModLauncher INSTANCE = null;
public static ModLauncher instance() {
if (INSTANCE == null) {
synchronized (ModLauncher.class) {
if (INSTANCE == null) {
INSTANCE = new ModLauncher();
}
}
}
return INSTANCE;
}
}
@@ -10,7 +10,7 @@ import org.objectweb.asm.commons.ClassRemapper;
import org.objectweb.asm.tree.*;
/**
* Transformer of FakeSkinManager for 1.13
* Transformer of FakeSkinManager for 1.13+
*/
public class FakeSkinManagerTransformer {
private static boolean needTransform = false;
@@ -19,11 +19,13 @@ public class FakeSkinManagerTransformer {
private final static String NEW_TARGET_CLASS = "net/minecraft/client/renderer/texture/ThreadDownloadImageData";
private final static String CALLBACK_CLASS = "net/minecraft/client/resources/SkinManager$SkinAvailableCallback";
/* No Need for Detecting 1.13
private static void init() {
if (!needInit) return;
needTransform = TARGET_CLASS == FMLDeobfuscatingRemapper.INSTANCE.unmap(TARGET_CLASS);
needInit = false;
}
*/
@TransformTarget(className = "customskinloader.fake.FakeSkinManager",
methodNames = {"<init>"},
@@ -31,8 +33,10 @@ public class FakeSkinManagerTransformer {
public static class InitTransformer implements IMethodTransformer {
@Override
public void transform(ClassNode cn, MethodNode mn) {
/* No Need for Detecting 1.13
init();
if (!needTransform) return;
*/
TransformerManager.logger.info("1.13 detected, FakeSkinManager will be transformed.");
ClassNameRemapper.remapClassName(cn, TARGET_CLASS, NEW_TARGET_CLASS);
MethodNameRemapper.remapMethodName(cn, CALLBACK_CLASS, "func_180521_a", "onSkinTextureAvailable");
@@ -1,30 +0,0 @@
package customskinloader.forge.transformer;
import customskinloader.forge.TransformerManager;
import net.minecraft.launchwrapper.IClassTransformer;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode;
public class LaunchWrapper implements IClassTransformer {
private TransformerManager transformerManager = new TransformerManager();
//LaunchWrapper
//From: https://github.com/RecursiveG/UniSkinMod/blob/1.9.4/src/main/java/org/devinprogress/uniskinmod/coremod/BaseAsmTransformer.java#L83-L114
public byte[] transform(String obfClassName, String className, byte[] bytes) {
if (!transformerManager.map.containsKey(className)) return bytes;//Check if should be transformed
//Parse bytes to ClassNode
ClassReader cr = new ClassReader(bytes);
ClassNode cn = new ClassNode();
cr.accept(cn, 0);
//Transform ClassNode
transformerManager.transform(cn, className, obfClassName);
//Parse Class Node to bytes
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
cn.accept(cw);
return cw.toByteArray();
}
}
@@ -1,33 +0,0 @@
package customskinloader.forge.transformer;
import cpw.mods.modlauncher.api.ITransformer;
import cpw.mods.modlauncher.api.ITransformerVotingContext;
import cpw.mods.modlauncher.api.TransformerVoteResult;
import customskinloader.forge.TransformerManager;
import net.minecraftforge.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
import org.objectweb.asm.tree.ClassNode;
import java.util.HashSet;
import java.util.Set;
public class ModLauncher implements ITransformer<ClassNode> {
private TransformerManager transformerManager = new TransformerManager();
//ModLauncher
public ClassNode transform(ClassNode input, ITransformerVotingContext context) {
return transformerManager.transform(input);
}
public TransformerVoteResult castVote(ITransformerVotingContext context) {
return TransformerVoteResult.YES;
}
public Set<Target> targets() {
Set<Target> sets = new HashSet<Target>();
for (String className : transformerManager.map.keySet()) {
String obfName = FMLDeobfuscatingRemapper.INSTANCE.unmap(className);
sets.add(Target.targetClass(obfName));
}
return sets;
}
}
@@ -14,6 +14,9 @@ import org.objectweb.asm.tree.MethodNode;
import customskinloader.forge.TransformerManager.IMethodTransformer;
import customskinloader.forge.TransformerManager.TransformTarget;
/**
* Transformer of Spectator Menu for 1.13-
*/
public class SpectatorMenuTransformer {
@TransformTarget(className="net.minecraft.client.gui.spectator.PlayerMenuObject",
methodNames={"<init>"},
@@ -31,12 +34,14 @@ public class SpectatorMenuTransformer {
if(ain.getOpcode()!=Opcodes.INVOKESTATIC)
continue;
/* No Need for Detecting 1.13
MethodInsnNode min = (MethodInsnNode)ain;
String deobfName = FMLDeobfuscatingRemapper.INSTANCE.map(min.owner);
if(!deobfName.equals("net/minecraft/client/entity/AbstractClientPlayer")) {//Fix 1.13
TransformerManager.logger.info("InvokeStatic to " + deobfName + " in PlayerMenuObject will be ignored.");
continue;
}
*/
if(!flag) {
//First InvokeStatic