Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
id "java"
id "java-library"
id "maven-publish"
id "eclipse"
id "net.minecrell.licenser" version "0.4.1"
}

Expand All @@ -25,6 +26,7 @@ repositories {
url = "https://maven.fabricmc.net/"
content {
includeGroup("net.fabricmc") // I'd like to deprecate procyon, so we don't need to maintain it
includeGroup("cuchaz")
}
}
}
Expand Down
58 changes: 51 additions & 7 deletions src/main/java/net/fabricmc/stitch/merge/ClassMerger.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@
import java.util.*;

public class ClassMerger {
// Fabric
private static final String SIDE_DESCRIPTOR = "Lnet/fabricmc/api/EnvType;";
private static final String ITF_DESCRIPTOR = "Lnet/fabricmc/api/EnvironmentInterface;";
private static final String ITF_LIST_DESCRIPTOR = "Lnet/fabricmc/api/EnvironmentInterfaces;";
private static final String SIDED_DESCRIPTOR = "Lnet/fabricmc/api/Environment;";
// Quilt
private static final String QUILT_CLIENT_DESC = "Lorg/quiltmc/loader/api/minecraft/ClientOnly;";
private static final String QUILT_SERVER_DESC = "Lorg/quiltmc/loader/api/minecraft/DedicatedServerOnly;";

private abstract class Merger<T> {
private final Map<String, T> entriesClient, entriesServer;
Expand Down Expand Up @@ -89,24 +93,41 @@ private static void visitItfAnnotation(AnnotationVisitor av, String side, List<S

public static class SidedClassVisitor extends ClassVisitor {
private final String side;
private boolean useQuilt = true;

public SidedClassVisitor(int api, ClassVisitor cv, String side) {
super(api, cv);
this.side = side;
}

public SidedClassVisitor setUseQuiltAnnotations(boolean use) {
useQuilt = use;
return this;
}

@Override
public void visitEnd() {
AnnotationVisitor av = cv.visitAnnotation(SIDED_DESCRIPTOR, true);
visitSideAnnotation(av, side);
if (useQuilt) {
cv.visitAnnotation("CLIENT".equals(side) ? QUILT_CLIENT_DESC : QUILT_SERVER_DESC, true);
} else {
AnnotationVisitor av = cv.visitAnnotation(SIDED_DESCRIPTOR, true);
visitSideAnnotation(av, side);
}
super.visitEnd();
}
}

private boolean useQuilt = true;

public ClassMerger() {

}

public ClassMerger setUseQuiltAnnotations(boolean use) {
useQuilt = use;
return this;
}

public byte[] merge(byte[] classClient, byte[] classServer) {
ClassReader readerC = new ClassReader(classClient);
ClassReader readerS = new ClassReader(classServer);
Expand Down Expand Up @@ -168,7 +189,22 @@ public byte[] merge(byte[] classClient, byte[] classServer) {
}
}

if (!clientItfs.isEmpty() || !serverItfs.isEmpty()) {
if (useQuilt) {
if (!clientItfs.isEmpty()) {
for (String itf : clientItfs) {
int ref = TypeReference.CLASS_EXTENDS | nodeOut.interfaces.indexOf(itf) << 8;
nodeOut.visitTypeAnnotation(ref, null, QUILT_CLIENT_DESC, false);
}
}

if (!serverItfs.isEmpty()) {
for (String itf : serverItfs) {
int ref = TypeReference.CLASS_EXTENDS | nodeOut.interfaces.indexOf(itf) << 8;
nodeOut.visitTypeAnnotation(ref, null, QUILT_SERVER_DESC, false);
}
}

} else if (!clientItfs.isEmpty() || !serverItfs.isEmpty()) {
AnnotationVisitor envInterfaces = nodeOut.visitAnnotation(ITF_LIST_DESCRIPTOR, false);
AnnotationVisitor eiArray = envInterfaces.visitArray("value");

Expand Down Expand Up @@ -201,8 +237,12 @@ public String getName(FieldNode entry) {

@Override
public void applySide(FieldNode entry, String side) {
AnnotationVisitor av = entry.visitAnnotation(SIDED_DESCRIPTOR, false);
visitSideAnnotation(av, side);
if (useQuilt) {
entry.visitAnnotation("CLIENT".equals(side) ? QUILT_CLIENT_DESC : QUILT_SERVER_DESC, false);
} else {
AnnotationVisitor av = entry.visitAnnotation(SIDED_DESCRIPTOR, false);
visitSideAnnotation(av, side);
}
}
}.merge(nodeOut.fields);

Expand All @@ -214,8 +254,12 @@ public String getName(MethodNode entry) {

@Override
public void applySide(MethodNode entry, String side) {
AnnotationVisitor av = entry.visitAnnotation(SIDED_DESCRIPTOR, false);
visitSideAnnotation(av, side);
if (useQuilt) {
entry.visitAnnotation("CLIENT".equals(side) ? QUILT_CLIENT_DESC : QUILT_SERVER_DESC, false);
} else {
AnnotationVisitor av = entry.visitAnnotation(SIDED_DESCRIPTOR, false);
visitSideAnnotation(av, side);
}
}
}.merge(nodeOut.methods);

Expand Down
15 changes: 12 additions & 3 deletions src/main/java/net/fabricmc/stitch/merge/JarMerger.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,16 @@ public Entry(Path path, BasicFileAttributes metadata, byte[] data) {
}
}

private static final ClassMerger CLASS_MERGER = new ClassMerger();
private static final ClassMerger CLASS_MERGER_QUILT = new ClassMerger().setUseQuiltAnnotations(true);
private static final ClassMerger CLASS_MERGER_FABRIC = new ClassMerger().setUseQuiltAnnotations(false);

private final StitchUtil.FileSystemDelegate inputClientFs, inputServerFs, outputFs;
private final Path inputClient, inputServer;
private final Map<String, Entry> entriesClient, entriesServer;
private final Set<String> entriesAll;
private boolean removeSnowmen = false;
private boolean offsetSyntheticsParams = false;
private boolean useQuiltAnnotations = true;

public JarMerger(File inputClient, File inputServer, File output) throws IOException {
if (output.exists()) {
Expand All @@ -79,6 +82,10 @@ public void enableSyntheticParamsOffset() {
offsetSyntheticsParams = true;
}

public void setUseQuiltAnnotations(boolean use) {
useQuiltAnnotations = use;
}

@Override
public void close() throws IOException {
inputClientFs.close();
Expand Down Expand Up @@ -170,7 +177,8 @@ public void merge() throws IOException {
result = entry1;
} else {
if (isClass) {
result = new Entry(entry1.path, entry1.metadata, CLASS_MERGER.merge(entry1.data, entry2.data));
ClassMerger classMerger = useQuiltAnnotations ? CLASS_MERGER_QUILT : CLASS_MERGER_FABRIC;
result = new Entry(entry1.path, entry1.metadata, classMerger.merge(entry1.data, entry2.data));
} else {
// FIXME: More heuristics?
result = entry1;
Expand All @@ -195,7 +203,8 @@ public void merge() throws IOException {
ClassVisitor visitor = writer;

if (side != null) {
visitor = new ClassMerger.SidedClassVisitor(StitchUtil.ASM_VERSION, visitor, side);
visitor = new ClassMerger.SidedClassVisitor(StitchUtil.ASM_VERSION, visitor, side)
.setUseQuiltAnnotations(useQuiltAnnotations);
}

if (removeSnowmen) {
Expand Down