aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.gradle.kts6
-rw-r--r--gradle/libs.versions.toml7
-rw-r--r--settings.gradle.kts1
-rw-r--r--testagent/build.gradle.kts14
-rw-r--r--testagent/src/main/java/moe/nea/firmament/testagent/AgentMain.java21
-rw-r--r--testagent/src/main/java/moe/nea/firmament/testagent/ProtectedToPublicClassRewriter.java31
-rw-r--r--testagent/src/main/java/moe/nea/firmament/testagent/ProtectedToPublicClassTransformer.java30
7 files changed, 109 insertions, 1 deletions
diff --git a/build.gradle.kts b/build.gradle.kts
index 05912a7..1d5478f 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -214,6 +214,9 @@ val hotswap by configurations.creating {
val nonModImplentation by configurations.creating {
configurations.implementation.get().extendsFrom(this)
}
+val testAgent by configurations.creating {
+ isVisible = false
+}
val configuredSourceSet = createIsolatedSourceSet("configured",
@@ -306,6 +309,7 @@ dependencies {
testImplementation("io.kotest:kotest-runner-junit5:6.0.0.M1")
+ testAgent(project(":testagent", configuration = "shadow"))
implementation(project(":symbols"))
ksp(project(":symbols"))
@@ -371,11 +375,13 @@ tasks.test {
val wd = file("build/testWorkDir")
workingDir(wd)
dependsOn(downloadTestRepo)
+ dependsOn(testAgent)
doFirst {
wd.mkdirs()
wd.resolve("config").deleteRecursively()
systemProperty("firmament.testrepo",
downloadTestRepo.flatMap { it.outputDirectory.asFile }.map { it.absolutePath }.get())
+ jvmArgs("-javaagent:${testAgent.singleFile.absolutePath}")
}
systemProperty("jdk.attach.allowAttachSelf", "true")
jvmArgs("-XX:+EnableDynamicAgentLoading")
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 83e1ae7..74de8e8 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -85,6 +85,9 @@ basicMath = "0.6.1"
# Update from https://mvnrepository.com/artifact/net.lenni0451.classtransform/core
classtransform = "1.14.0"
+# Update from https://mvnrepository.com/artifact/org.ow2.asm/asm/
+asm = "9.7.1"
+
[libraries]
minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" }
fabric_loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric_loader" }
@@ -124,6 +127,8 @@ basicMath = { module = "me.shedaniel.cloth:basic-math", version.ref = "basicMath
classTransform-mixinsTranslator = { module = "net.lenni0451.classtransform:mixinstranslator", version.ref = "classtransform" }
classTransform-core = { module = "net.lenni0451.classtransform:core", version.ref = "classtransform" }
+asm = { module = "org.ow2.asm:asm", version.ref = "asm" }
+
[bundles]
runtime_required = [
"rei_fabric",
@@ -145,4 +150,4 @@ kotlin_plugin_serialization = { id = "org.jetbrains.kotlin.plugin.serialization"
kotlin_plugin_powerassert = { id = "org.jetbrains.kotlin.plugin.power-assert", version.ref = "kotlin" }
kotlin_plugin_ksp = { id = "com.google.devtools.ksp", version.ref = "kotlin_ksp" }
loom = { id = "dev.architectury.loom", version.ref = "loom" }
-shadow = { id = "com.github.johnrengelman.shadow",version="8.1.1" }
+shadow = { id = "com.github.johnrengelman.shadow", version = "8.1.1" }
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 5c4a313..aef468a 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -37,3 +37,4 @@ rootProject.name = "Firmament"
include("symbols")
include("javaplugin")
+include("testagent")
diff --git a/testagent/build.gradle.kts b/testagent/build.gradle.kts
new file mode 100644
index 0000000..3bd8c8c
--- /dev/null
+++ b/testagent/build.gradle.kts
@@ -0,0 +1,14 @@
+plugins {
+ java
+ alias(libs.plugins.shadow)
+}
+dependencies {
+ implementation(libs.asm)
+}
+tasks.withType<Jar> {
+ val agentMain = "moe.nea.firmament.testagent.AgentMain"
+ manifest.attributes(
+ "Agent-Class" to agentMain,
+ "Premain-Class" to agentMain,
+ )
+}
diff --git a/testagent/src/main/java/moe/nea/firmament/testagent/AgentMain.java b/testagent/src/main/java/moe/nea/firmament/testagent/AgentMain.java
new file mode 100644
index 0000000..79023d8
--- /dev/null
+++ b/testagent/src/main/java/moe/nea/firmament/testagent/AgentMain.java
@@ -0,0 +1,21 @@
+package moe.nea.firmament.testagent;
+
+import java.lang.instrument.Instrumentation;
+
+public class AgentMain {
+
+ public static void premain(
+ String agentArgs, Instrumentation inst) {
+ System.out.println("Pre-Main Firmament Test Agent");
+ AgentMain.inject(inst);
+ }
+
+ public static void agentmain(
+ String agentArgs, Instrumentation inst) {
+ System.out.println("Injected Firmament Test Agent");
+ AgentMain.inject(inst);
+ }
+
+ private static void inject(Instrumentation inst) {
+ inst.addTransformer(new ProtectedToPublicClassTransformer(inst)); }
+}
diff --git a/testagent/src/main/java/moe/nea/firmament/testagent/ProtectedToPublicClassRewriter.java b/testagent/src/main/java/moe/nea/firmament/testagent/ProtectedToPublicClassRewriter.java
new file mode 100644
index 0000000..7d9aa56
--- /dev/null
+++ b/testagent/src/main/java/moe/nea/firmament/testagent/ProtectedToPublicClassRewriter.java
@@ -0,0 +1,31 @@
+package moe.nea.firmament.testagent;
+
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+public class ProtectedToPublicClassRewriter extends ClassVisitor {
+ public ProtectedToPublicClassRewriter(ClassWriter writer) {
+ super(Opcodes.ASM9, writer);
+ }
+
+ int makePublic(int flags) {
+ if ((flags & Opcodes.ACC_PROTECTED) != 0)
+ return (flags & ~Opcodes.ACC_PROTECTED) | Opcodes.ACC_PUBLIC;
+ if ((flags & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE)) == 0)
+ return flags | Opcodes.ACC_PUBLIC;
+ return flags;
+ }
+
+ @Override
+ public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
+ return super.visitField(makePublic(access), name, descriptor, signature, value);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
+ return super.visitMethod(makePublic(access), name, descriptor, signature, exceptions);
+ }
+}
diff --git a/testagent/src/main/java/moe/nea/firmament/testagent/ProtectedToPublicClassTransformer.java b/testagent/src/main/java/moe/nea/firmament/testagent/ProtectedToPublicClassTransformer.java
new file mode 100644
index 0000000..5d59035
--- /dev/null
+++ b/testagent/src/main/java/moe/nea/firmament/testagent/ProtectedToPublicClassTransformer.java
@@ -0,0 +1,30 @@
+package moe.nea.firmament.testagent;
+
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.security.ProtectionDomain;
+
+public class ProtectedToPublicClassTransformer implements ClassFileTransformer {
+ public ProtectedToPublicClassTransformer(Instrumentation inst) {
+ }
+
+ @Override
+ public byte[] transform(ClassLoader loader,
+ String className,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain,
+ byte[] classfileBuffer)
+ throws IllegalClassFormatException {
+ if (!className.startsWith("net/minecraft/")) return classfileBuffer;
+ if (classfileBuffer == null) return null;
+ var reader = new ClassReader(classfileBuffer);
+ var writer = new ClassWriter(0);
+ var transformer = new ProtectedToPublicClassRewriter(writer);
+ reader.accept(transformer, 0);
+ return writer.toByteArray();
+ }
+}