Mixin remapper + fixes. Now runs on notch names
parent
dffcc5a9d8
commit
856e8b5c1f
|
@ -13,7 +13,7 @@ targetCompatibility = 1.8
|
||||||
|
|
||||||
group = 'com.openmodloader'
|
group = 'com.openmodloader'
|
||||||
archivesBaseName = project.name
|
archivesBaseName = project.name
|
||||||
version = '0.0.10-SNAPSHOT'
|
version = '0.0.11-SNAPSHOT'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -56,7 +56,7 @@ dependencies {
|
||||||
shade ('enigma-asm:enigma:0.12.0.33:lib'){
|
shade ('enigma-asm:enigma:0.12.0.33:lib'){
|
||||||
exclude group: 'org.ow2.asm'
|
exclude group: 'org.ow2.asm'
|
||||||
}
|
}
|
||||||
shade 'OpenModLoader.tiny-remapper:tiny-remapper:+'
|
shade 'OpenModLoader.tiny-remapper:tiny-remapper:0.1.0.7'
|
||||||
shade 'net.sf.jopt-simple:jopt-simple:5.0.4'
|
shade 'net.sf.jopt-simple:jopt-simple:5.0.4'
|
||||||
shade 'org.apache.logging.log4j:log4j-api:2.11.0'
|
shade 'org.apache.logging.log4j:log4j-api:2.11.0'
|
||||||
shade 'org.apache.logging.log4j:log4j-core:2.11.0'
|
shade 'org.apache.logging.log4j:log4j-core:2.11.0'
|
||||||
|
|
|
@ -66,6 +66,11 @@ public class RunClientTask extends JavaExec {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
libs.add(Constants.MINECRAFT_CLIENT_JAR.get(extension).getAbsolutePath());
|
libs.add(Constants.MINECRAFT_CLIENT_JAR.get(extension).getAbsolutePath());
|
||||||
|
|
||||||
|
//Removes the deobf jars
|
||||||
|
libs.removeIf(s -> s.contains(Constants.MINECRAFT_FINAL_JAR.get(extension).getName()));
|
||||||
|
libs.removeIf(s -> s.contains(getProject().getName() + "-" + getProject().getVersion() + "-deobf.jar"));
|
||||||
|
|
||||||
classpath(libs);
|
classpath(libs);
|
||||||
|
|
||||||
args("--launchTarget", "oml", "--accessToken", "NOT_A_TOKEN", "--version", extension.version, "--assetIndex", version.assetIndex.id, "--assetsDir", new File(extension.getUserCache(), "assets-" + extension.version).getAbsolutePath());
|
args("--launchTarget", "oml", "--accessToken", "NOT_A_TOKEN", "--version", extension.version, "--assetIndex", version.assetIndex.id, "--assetsDir", new File(extension.getUserCache(), "assets-" + extension.version).getAbsolutePath());
|
||||||
|
@ -85,7 +90,7 @@ public class RunClientTask extends JavaExec {
|
||||||
LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class);
|
LoomGradleExtension extension = this.getProject().getExtensions().getByType(LoomGradleExtension.class);
|
||||||
List<String> args = new ArrayList<>();
|
List<String> args = new ArrayList<>();
|
||||||
args.add("-Djava.library.path=" + Constants.MINECRAFT_NATIVES.get(extension).getAbsolutePath());
|
args.add("-Djava.library.path=" + Constants.MINECRAFT_NATIVES.get(extension).getAbsolutePath());
|
||||||
args.add("-XstartOnFirstThread"); //Fixes lwjgl starting on an incorrect thread
|
//args.add("-XstartOnFirstThread"); //Fixes lwjgl starting on an incorrect thread
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,17 +25,21 @@
|
||||||
package net.fabricmc.loom.util;
|
package net.fabricmc.loom.util;
|
||||||
|
|
||||||
import net.fabricmc.loom.LoomGradleExtension;
|
import net.fabricmc.loom.LoomGradleExtension;
|
||||||
import net.fabricmc.tinyremapper.OutputConsumerPath;
|
import net.fabricmc.tinyremapper.*;
|
||||||
import net.fabricmc.tinyremapper.TinyRemapper;
|
|
||||||
import net.fabricmc.tinyremapper.TinyUtils;
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.gradle.api.Project;
|
import org.gradle.api.Project;
|
||||||
|
import org.objectweb.asm.ClassReader;
|
||||||
|
import org.objectweb.asm.ClassWriter;
|
||||||
|
import org.objectweb.asm.Type;
|
||||||
|
import org.objectweb.asm.tree.AnnotationNode;
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
import org.objectweb.asm.tree.FieldNode;
|
||||||
|
import org.objectweb.asm.tree.MethodNode;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class ModRemapper {
|
public class ModRemapper {
|
||||||
|
|
||||||
|
@ -77,6 +81,7 @@ public class ModRemapper {
|
||||||
|
|
||||||
TinyRemapper remapper = TinyRemapper.newRemapper()
|
TinyRemapper remapper = TinyRemapper.newRemapper()
|
||||||
.withMappings(TinyUtils.createTinyMappingProvider(mappings, fromM, toM))
|
.withMappings(TinyUtils.createTinyMappingProvider(mappings, fromM, toM))
|
||||||
|
.withRemapperExtension(new MixinRemapper())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -100,4 +105,131 @@ public class ModRemapper {
|
||||||
//Add the deobf jar to be uploaded to maven
|
//Add the deobf jar to be uploaded to maven
|
||||||
project.getArtifacts().add("archives", deobfJar);
|
project.getArtifacts().add("archives", deobfJar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class MixinRemapper implements IRemapperExtension{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] handleUnmappedClass(byte[] inBytes, TinyRemapper remapper) {
|
||||||
|
//I know this isnt the fastest, but its the easiest
|
||||||
|
ClassNode classNode = readClassFromBytes(inBytes);
|
||||||
|
if(isMixin(classNode)){
|
||||||
|
String target = getMixinTarget(classNode);
|
||||||
|
System.out.println("Remapping mixin (" + classNode.name + ") targeting: " + target);
|
||||||
|
for(MethodNode methodNode : classNode.methods){
|
||||||
|
if(needsTargetMap(methodNode.visibleAnnotations)){
|
||||||
|
methodNode.visibleAnnotations.add(createTargetMap(methodNode, target, remapper));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(FieldNode fieldNode : classNode.fields){
|
||||||
|
if(needsTargetMap(fieldNode.visibleAnnotations)){
|
||||||
|
//fieldNode.visibleAnnotations.add(createTargetMap(fieldNode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return writeClassToBytes(classNode);
|
||||||
|
}
|
||||||
|
return inBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AnnotationNode createTargetMap(MethodNode methodNode, String targetClass, TinyRemapper remapper){
|
||||||
|
AnnotationNode targetMapNode = new AnnotationNode("Lme/modmuss50/fusion/api/TargetMap;");
|
||||||
|
String deobfTarget = methodNode.name + methodNode.desc;
|
||||||
|
if(getRewriteTarget(methodNode).isPresent()){
|
||||||
|
deobfTarget = getRewriteTarget(methodNode).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(deobfTarget.equals("<init>")){
|
||||||
|
//No need to handle constructors, may need to do something about the desc but we will see
|
||||||
|
return targetMapNode;
|
||||||
|
}
|
||||||
|
String oldName = deobfTarget.substring(0, deobfTarget.indexOf("("));
|
||||||
|
String oldDesc = deobfTarget.substring(deobfTarget.lastIndexOf("("));
|
||||||
|
|
||||||
|
String newName = remapper.remapper.mapMethodName(targetClass.replaceAll("\\.", "/"), oldName, oldDesc);
|
||||||
|
String newDesc = remapper.remapper.mapDesc(oldDesc);
|
||||||
|
|
||||||
|
System.out.println(oldName + oldDesc + " -> " + newName + newDesc);
|
||||||
|
targetMapNode.visit("value", newName + newDesc);
|
||||||
|
return targetMapNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isMixin(ClassNode classNode){
|
||||||
|
if(classNode.visibleAnnotations == null){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for(AnnotationNode annotation : classNode.visibleAnnotations){
|
||||||
|
if(annotation.desc.equals("Lme/modmuss50/fusion/api/Mixin;")){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getMixinTarget(ClassNode classNode){
|
||||||
|
if(classNode.visibleAnnotations == null){
|
||||||
|
throw new RuntimeException(classNode.name + " is not a mixin!");
|
||||||
|
}
|
||||||
|
for(AnnotationNode annotation : classNode.visibleAnnotations){
|
||||||
|
if(annotation.desc.equals("Lme/modmuss50/fusion/api/Mixin;")){
|
||||||
|
for (int i = 0; i < annotation.values.size(); i++) {
|
||||||
|
Object value = annotation.values.get(i);
|
||||||
|
if(value instanceof String && value.toString().equals("value")){
|
||||||
|
Type target = (Type) annotation.values.get(i + 1);
|
||||||
|
return target.getClassName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RuntimeException(classNode.name + " is not a valid mixin!");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<String> getRewriteTarget(MethodNode methodNode){
|
||||||
|
if(methodNode.visibleAnnotations == null){
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
for(AnnotationNode annotation : methodNode.visibleAnnotations){
|
||||||
|
if(annotation.desc.equals("Lme/modmuss50/fusion/api/Rewrite;")){
|
||||||
|
for (int i = 0; i < annotation.values.size(); i++) {
|
||||||
|
Object value = annotation.values.get(i);
|
||||||
|
if(value instanceof String && value.toString().equals("target")){
|
||||||
|
return Optional.of((String) annotation.values.get(i + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean needsTargetMap(List<AnnotationNode> annotationNodes){
|
||||||
|
if(annotationNodes == null){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for(AnnotationNode annotation : annotationNodes){
|
||||||
|
if(annotation.desc.equals("Lme/modmuss50/fusion/api/Rewrite;")){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(annotation.desc.equals("Lme/modmuss50/fusion/api/Inject;")){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static ClassNode readClassFromBytes(byte[] bytes) {
|
||||||
|
ClassNode classNode = new org.objectweb.asm.tree.ClassNode();
|
||||||
|
ClassReader classReader = new ClassReader(bytes);
|
||||||
|
classReader.accept(classNode, 0);
|
||||||
|
return classNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] writeClassToBytes(ClassNode classNode) {
|
||||||
|
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
|
||||||
|
classNode.accept(writer);
|
||||||
|
return writer.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue