add environment stripping, fix more bugs
All checks were successful
Publish to snapshot maven / build (push) Successful in 24s

This commit is contained in:
moehreag 2024-08-10 22:54:05 +02:00
parent cbc44f5147
commit 7ed5ed6f09
6 changed files with 147 additions and 11 deletions

View file

@ -7,7 +7,7 @@ plugins {
} }
group = "dev.frogmc" group = "dev.frogmc"
version = "0.0.1-alpha.19" version = "0.0.1-alpha.20"
repositories { repositories {
maven { maven {

View file

@ -14,10 +14,9 @@ public enum Env {
/** /**
* The physical (dedicated) server environment * The physical (dedicated) server environment
*/ */
SERVER("SERVER", "server"), SERVER("SERVER", "server")
; ;
private final String mixinName, identifier; private final String mixinName, identifier;
/** /**
@ -37,4 +36,12 @@ public enum Env {
public String getIdentifier() { public String getIdentifier() {
return this.identifier; return this.identifier;
} }
public @interface Client {
}
public @interface Server {
}
} }

View file

@ -8,10 +8,7 @@ import java.util.concurrent.ConcurrentSkipListSet;
import dev.frogmc.frogloader.impl.launch.FrogLauncher; import dev.frogmc.frogloader.impl.launch.FrogLauncher;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.*;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class AccessWidener { public class AccessWidener {
private static final AccessWidener INSTANCE = new AccessWidener(); private static final AccessWidener INSTANCE = new AccessWidener();
@ -30,7 +27,7 @@ public class AccessWidener {
get().loadFromData(data); get().loadFromData(data);
} }
public static ClassVisitor processClass(ClassVisitor cv, String className) { public static ClassVisitor processClass(ClassReader reader, ClassVisitor cv, String className) {
return get().process(cv, className); return get().process(cv, className);
} }

View file

@ -9,17 +9,21 @@ import org.objectweb.asm.ClassWriter;
public interface AsmTransformer { public interface AsmTransformer {
List<AsmTransformer> TRANSFORMERS = List.of( List<AsmTransformer> TRANSFORMERS = List.of(
new EnvFilter(),
AccessWidener::processClass AccessWidener::processClass
); );
ClassVisitor transform(ClassVisitor cv, String name); ClassVisitor transform(ClassReader reader, ClassVisitor cv, String name);
static byte[] transform(byte[] clazz, String name) { static byte[] transform(byte[] clazz, String name) {
ClassReader reader = new ClassReader(clazz); ClassReader reader = new ClassReader(clazz);
ClassWriter writer = new ClassWriter(0); ClassWriter writer = new ClassWriter(0);
ClassVisitor cv = writer; ClassVisitor cv = writer;
for (AsmTransformer fcv : TRANSFORMERS) { for (AsmTransformer fcv : TRANSFORMERS) {
cv = fcv.transform(cv, name); cv = fcv.transform(reader, cv, name);
}
if (cv == writer) {
return clazz;
} }
reader.accept(cv, 0); reader.accept(cv, 0);
return writer.toByteArray(); return writer.toByteArray();

View file

@ -0,0 +1,128 @@
package dev.frogmc.frogloader.impl.launch.transformer;
import java.util.HashSet;
import java.util.Set;
import dev.frogmc.frogloader.api.env.Env;
import dev.frogmc.frogloader.impl.launch.FrogLauncher;
import dev.frogmc.thyroxine.api.data.Member;
import org.objectweb.asm.*;
public class EnvFilter implements AsmTransformer {
@Override
public ClassVisitor transform(ClassReader reader, ClassVisitor cv, String name) {
EnvDataCollector collector = new EnvDataCollector(FrogLauncher.getInstance().getEnv(), name);
reader.accept(collector, ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES);
if (collector.classes.isEmpty() && collector.methods.isEmpty() && collector.fields.isEmpty()) {
return cv;
}
return new Stripper(collector, name);
}
private static class Stripper extends ClassVisitor {
private final EnvDataCollector collector;
private final String className;
protected Stripper(EnvDataCollector collector, String name) {
super(FrogLauncher.ASM_VERSION, collector);
this.collector = collector;
this.className = name;
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
if (!collector.classes.contains(name)) {
super.visit(version, access, name, signature, superName, interfaces);
}
}
@Override
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
if (!collector.fields.contains(new Member(className, name, descriptor))) {
return super.visitField(access, name, descriptor, signature, value);
}
return null;
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
if (!collector.methods.contains(new Member(className, name, descriptor))) {
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
return null;
}
}
private static class EnvDataCollector extends ClassVisitor {
private final Set<String> classes = new HashSet<>(0);
private final Set<Member> methods = new HashSet<>(0);
private final Set<Member> fields = new HashSet<>(0);
private final String envDescriptor;
private final String className;
protected EnvDataCollector(Env env, String name) {
super(FrogLauncher.ASM_VERSION);
if (env == Env.CLIENT) {
envDescriptor = Env.Client.class.descriptorString();
} else if (env == Env.SERVER) {
envDescriptor = Env.Server.class.descriptorString();
} else {
throw new IllegalArgumentException("Unsupported environment: " + env);
}
this.className = name;
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
if (descriptor.equals(envDescriptor)) {
classes.add(className);
}
return super.visitAnnotation(descriptor, visible);
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
if (mv != null) {
mv = new MethodVisitor(FrogLauncher.ASM_VERSION, mv) {
@Override
public AnnotationVisitor visitAnnotation(String aDesc, boolean visible) {
if (aDesc.equals(envDescriptor)) {
methods.add(new Member(className, name, descriptor));
}
return super.visitAnnotation(aDesc, visible);
}
};
}
return mv;
}
@Override
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
FieldVisitor fv = super.visitField(access, name, descriptor, signature, value);
if (fv != null) {
fv = new FieldVisitor(FrogLauncher.ASM_VERSION, fv) {
@Override
public AnnotationVisitor visitAnnotation(String aDesc, boolean visible) {
if (aDesc.equals(envDescriptor)) {
fields.add(new Member(className, name, descriptor));
}
return super.visitAnnotation(aDesc, visible);
}
};
}
return fv;
}
}
}

View file

@ -135,7 +135,7 @@ public class MinecraftGamePlugin implements GamePlugin {
URL resource = this.getClass().getResource(""); URL resource = this.getClass().getResource("");
String data; String data;
if (resource != null) { if (resource != null) {
data = new BufferedReader(new InputStreamReader(resource.openStream())).lines().collect(Collectors.joining()); data = new BufferedReader(new InputStreamReader(resource.openStream())).lines().collect(Collectors.joining("\n"));
} else { } else {
data = Files.readString(Paths.get(mappingPath)); data = Files.readString(Paths.get(mappingPath));
} }