Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite LWJGLTransformer #300

Open
wants to merge 7 commits into
base: experimental/foundation
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -8,65 +8,121 @@
import org.objectweb.asm.commons.ClassRemapper;
import org.objectweb.asm.commons.Remapper;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;

import java.io.IOException;
import java.util.Set;
import java.util.stream.Collectors;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;

public class LWJGLTransformer implements IClassTransformer {
private static final LWJGLXRemapper INSTANCE = new LWJGLXRemapper();
@Override
public byte[] transform(String s, String s1, byte[] bytes) {
if (!s1.startsWith("org.lwjgl.")) {
return bytes;
}
String lwjglxName = s.replace("org.lwjgl.", "org.lwjglx.");
byte[] lwjglxBytes;
try {
lwjglxBytes = Launch.classLoader.testGetClassBytes(lwjglxName);
} catch (IOException e) {
return bytes;
}
if (lwjglxBytes == null) {
return bytes;
}
ClassReader lwjglxReader = new ClassReader(lwjglxBytes);
ClassWriter writer = new ClassWriter(0);
ClassVisitor classVisitor = new ClassRemapper(writer, INSTANCE);
lwjglxReader.accept(classVisitor, 0);
lwjglxBytes = writer.toByteArray();
if (bytes == null) {
return lwjglxBytes;
}
private final HashMap<String, MergeTransformer> mergeTransformers = new HashMap<>();

ClassNode lwjglNode = new ClassNode();
ClassReader lwjglReader = new ClassReader(bytes);
lwjglReader.accept(lwjglNode, 0);

lwjglxReader = new ClassReader(lwjglxBytes);
ClassNode lwjglxNode = new ClassNode();
lwjglxReader.accept(lwjglxNode, 0);
Set<String> methods = lwjglNode.methods.stream().map(m -> m.name + m.desc).collect(Collectors.toSet());
lwjglxNode.methods.forEach(m -> {
if (!methods.contains(m.name + m.desc)) {
lwjglNode.methods.add(m);
public LWJGLTransformer(){
mergeTransformers.put("org.lwjgl.openal.AL", (lwjgl, lwjglx, methods, fields) -> lwjglx.methods.stream().filter(m -> m.name.equals("destroy"))
.forEach(methodNode -> methods.put(methodNode.name + methodNode.desc, methodNode)));
}

@Override
public byte[] transform(String unusedString, String name, byte[] bytes) {
// TODO : edit the caches in ClassLoader : cachedResources, negativeResourceCache
if (!name.startsWith("org.lwjgl.")) {
return bytes; // ignored
} else {
// reload the lwjgl base codes
try {
bytes = null;
var itr = Launch.classLoader.findResources(name.replace('.', '/').concat(".class")).asIterator();
while (itr.hasNext()) {
var url = itr.next();
if (!url.getPath().contains("lwjgl-2")) {
try (InputStream stream = url.openStream()) {
bytes = stream.readAllBytes();
}
}
}

} catch (IOException e) {
bytes = null;
}
});
Set<String> fields = lwjglNode.fields.stream().map(f -> f.name + f.desc).collect(Collectors.toSet());
lwjglxNode.fields.forEach(f -> {
if (!fields.contains(f.name + f.desc)) {
lwjglNode.fields.add(f);

if (bytes == null) {
// Not present
String lwjglxName = "org.lwjglx." + name.substring(10);
byte[] lwjglxBytes;
try {
lwjglxBytes = Launch.classLoader.testGetClassBytes(lwjglxName);
} catch (IOException e) {
return null;
}
if (lwjglxBytes == null) return null;
else {
ClassReader lwjglxReader = new ClassReader(lwjglxBytes);
ClassWriter writer = new ClassWriter(0);
ClassVisitor classVisitor = new ClassRemapper(writer, INSTANCE);
lwjglxReader.accept(classVisitor, 0);
return writer.toByteArray();
}
} else {
// If exists
String lwjglxName = "org.lwjglx." + name.substring(10);
byte[] lwjglxBytes;
try {
lwjglxBytes = Launch.classLoader.testGetClassBytes(lwjglxName);
} catch (IOException e) {
return null;
}
if (lwjglxBytes == null) return bytes;

ClassReader lwjglxReader = new ClassReader(lwjglxBytes);
ClassNode lwjglxNode = new ClassNode();
lwjglxReader.accept(new ClassRemapper(lwjglxNode, INSTANCE), 0);

ClassNode lwjglNode = new ClassNode();
ClassReader lwjglReader = new ClassReader(bytes);
lwjglReader.accept(lwjglNode, 0);

HashMap<String, MethodNode> methods = new HashMap<>();
for (MethodNode mn : lwjglxNode.methods) {
methods.put(mn.name + mn.desc, mn);
}
for (MethodNode mn : lwjglNode.methods) {
methods.put(mn.name + mn.desc, mn);
}

HashMap<String, FieldNode> fields = new HashMap<>();
for (FieldNode mn : lwjglxNode.fields) {
fields.put(mn.name + mn.desc, mn);
}
for (FieldNode mn : lwjglNode.fields) {
fields.put(mn.name + mn.desc, mn);
}

if (mergeTransformers.containsKey(name)) {
mergeTransformers.get(name).runMergeTransform(lwjglNode, lwjglxNode, methods, fields);
}

lwjglNode.fields = List.of(fields.values().toArray(FieldNode[]::new));
lwjglNode.methods = List.of(methods.values().toArray(MethodNode[]::new));
ClassWriter out = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
lwjglNode.accept(out);
return out.toByteArray();
}
});
if (s1.equals("org.lwjgl.openal.AL")) {
lwjglNode.methods.removeIf(m -> m.name.equals("destroy"));
lwjglxNode.methods.stream().filter(m -> m.name.equals("destroy")).forEach(m -> lwjglNode.methods.add(m));
}
ClassWriter out = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
lwjglNode.accept(out);
return out.toByteArray();
}

@FunctionalInterface
private interface MergeTransformer {
void runMergeTransform(ClassNode lwjgl, ClassNode lwjglx, HashMap<String, MethodNode> methods, HashMap<String, FieldNode> fields);
}

@Override
public int getPriority() {
return Integer.MAX_VALUE;
}

private static final LWJGLXRemapper INSTANCE = new LWJGLXRemapper();
static class LWJGLXRemapper extends Remapper {

@Override
Expand All @@ -82,5 +138,4 @@ public String map(String typeName) {
}

}

}
}