mirror of
https://github.com/xfl03/MCCustomSkinLoader.git
synced 2026-11-12 21:17:38 +00:00
Try to support 1.13 forge
This commit is contained in:
1 parent
7bbfd19bfd
commit
4cb1e348bb
12 files changed
+177
-112
No files matched your search
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"transformers": "transformers.js"
|
||||
}
|
||||
@@ -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"
|
||||
@@ -6,6 +6,7 @@
|
||||
"version": "${modFullVersion}",
|
||||
"url": "https://github.com/xfl03/MCCustomSkinLoader",
|
||||
"authorList": ["xfl03", "JLChnToZ"],
|
||||
"credits": "GPLv3"
|
||||
"credits": "GPLv3",
|
||||
"clientSideOnly": true
|
||||
}
|
||||
]
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user