From 03b23957827c42d5df5a11f3d07f807c5343e87e Mon Sep 17 00:00:00 2001
From: embeddedt <42941056+embeddedt@users.noreply.github.com>
Date: Thu, 6 Jul 2023 18:42:50 -0400
Subject: [PATCH] Add custom agent to work around
https://github.com/FabricMC/fabric-loader/issues/817
---
.gitignore | 1 +
build.gradle | 2 +-
fabric/build.gradle | 16 ++++
settings.gradle | 1 +
test_agent/build.gradle | 86 +++++++++++++++++++
.../embeddedt/modernfix/testing/Agent.java | 61 +++++++++++++
.../modernfix/testing/AgentHooks.java | 17 ++++
7 files changed, 183 insertions(+), 1 deletion(-)
create mode 100644 test_agent/build.gradle
create mode 100644 test_agent/src/main/java/org/embeddedt/modernfix/testing/Agent.java
create mode 100644 test_agent/src/main/java/org/embeddedt/modernfix/testing/AgentHooks.java
diff --git a/.gitignore b/.gitignore
index 3241d732..f427fdd2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@ media
classes/
.architectury-transformer/
fabric/fabricloader.log
+fabric/test_run
# Changelog
CHANGELOG.md
diff --git a/build.gradle b/build.gradle
index d9368c1b..d383f731 100644
--- a/build.gradle
+++ b/build.gradle
@@ -93,7 +93,7 @@ allprojects {
}
}
-subprojects {
+configure(subprojects.findAll {it.name == "common" || it.name == "forge" || it.name == "fabric"}) {
apply plugin: "dev.architectury.loom"
loom {
diff --git a/fabric/build.gradle b/fabric/build.gradle
index 02c657f9..1b813a9e 100644
--- a/fabric/build.gradle
+++ b/fabric/build.gradle
@@ -22,6 +22,10 @@ configurations {
include.extendsFrom modIncludeImplementation
modImplementation.extendsFrom modIncludeImplementation
+
+ testAgent {
+ canBeConsumed = false
+ }
}
dependencies {
@@ -51,10 +55,22 @@ dependencies {
testImplementation("org.assertj:assertj-core:3.19.0")
testImplementation("com.google.guava:guava-testlib:21.0")
testImplementation("org.mockito:mockito-junit-jupiter:5.3.1")
+
+ testAgent(project("path": ":test_agent", "configuration": "agentJar"))
}
test {
useJUnitPlatform()
+ def runDir = file('test_run')
+ doFirst() {
+ runDir.mkdir()
+ }
+ workingDir = runDir
+
+ // inject our custom agent to fix #817
+ FileCollection agentFile = configurations.getByName("testAgent")
+ jvmArgs "-javaagent:${agentFile.singleFile.absolutePath}"
+ dependsOn(agentFile)
}
processResources {
diff --git a/settings.gradle b/settings.gradle
index 8a77caf9..4afff011 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -7,6 +7,7 @@ pluginManagement {
}
}
+include("test_agent")
include("common")
include("fabric")
include("forge")
diff --git a/test_agent/build.gradle b/test_agent/build.gradle
new file mode 100644
index 00000000..2141b87d
--- /dev/null
+++ b/test_agent/build.gradle
@@ -0,0 +1,86 @@
+plugins {
+ //id 'com.github.johnrengelman.shadow' version '7.1.2'
+ id 'java'
+}
+
+group 'org.embeddedt'
+archivesBaseName = 'modernfix-test-agent'
+version '1.0'
+
+sourceCompatibility = '1.8'
+targetCompatibility = '1.8'
+
+repositories {
+ mavenCentral()
+ mavenLocal()
+ maven {
+ name = 'forge'
+ url = 'https://maven.minecraftforge.net/'
+ }
+}
+
+/*
+
+shadowJar {
+ relocate 'net.bytebuddy.agent', 'org.embeddedt.modernfix.testing.shadow.bytebuddyagent'
+ relocate 'org.objectweb.asm', 'org.embeddedt.modernfix.testing.shadow.asm'
+}
+
+
+
+shadowJar {
+ project.configurations.implementation.canBeResolved = true
+ configurations = [project.configurations.implementation]
+}
+ */
+dependencies {
+ compileOnly "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
+ implementation "org.ow2.asm:asm-tree:9.1"
+ implementation "org.ow2.asm:asm-commons:9.1"
+ implementation "org.ow2.asm:asm-util:9.1"
+
+ //implementation('net.bytebuddy:byte-buddy-agent:1.12.22')
+}
+
+tasks.withType(JavaCompile) {
+ // ensure that the encoding is set to UTF-8, no matter what the system default is
+ // this fixes some edge cases with special characters not displaying correctly
+ // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
+ // If Javadoc is generated, this must be specified in that task too.
+ options.encoding = "UTF-8"
+}
+
+jar {
+ manifest {
+ attributes(
+ "Premain-Class": "org.embeddedt.modernfix.testing.Agent",
+ "Can-Redefine-Classes": false,
+ "Can-Set-Native-Method-Prefix": false
+ )
+ }
+}
+/*
+
+shadowJar {
+ archiveBaseName.set('modernfix-test-agent')
+ archiveClassifier.set('')
+ archiveVersion.set('v1')
+}
+
+ */
+
+configurations {
+ agentJar {
+ canBeConsumed = true
+ canBeResolved = false
+ }
+}
+
+artifacts {
+ agentJar(jar)
+}
+/*
+project.tasks.shadowJar.dependsOn build
+defaultTasks 'shadowJar'
+
+ */
\ No newline at end of file
diff --git a/test_agent/src/main/java/org/embeddedt/modernfix/testing/Agent.java b/test_agent/src/main/java/org/embeddedt/modernfix/testing/Agent.java
new file mode 100644
index 00000000..b7b69479
--- /dev/null
+++ b/test_agent/src/main/java/org/embeddedt/modernfix/testing/Agent.java
@@ -0,0 +1,61 @@
+package org.embeddedt.modernfix.testing;
+
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.security.ProtectionDomain;
+import java.util.ListIterator;
+
+public class Agent {
+ /**
+ * Simple agent that transforms Fabric Loader to never mark game JARs as system libraries.
+ *
+ * Ugly, but usable workaround for issue #817
+ * on the Loader bug tracker.
+ */
+ public static void premain(String args, Instrumentation instrumentation) {
+ instrumentation.addTransformer(new ClassFileTransformer() {
+ @Override
+ public byte[] transform(ClassLoader loader, String className, Class> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
+ if(className.equals("net/fabricmc/loader/impl/game/LibClassifier")) {
+ ClassNode node = new ClassNode();
+ ClassReader reader = new ClassReader(classfileBuffer);
+ reader.accept(node, 0);
+ for(MethodNode m : node.methods) {
+ if(m.name.equals("")) {
+ ListIterator iter = m.instructions.iterator();
+ int addMatches = 0;
+ while(iter.hasNext()) {
+ AbstractInsnNode n = iter.next();
+ if(n instanceof MethodInsnNode) {
+ MethodInsnNode invokeNode = (MethodInsnNode)n;
+ if(invokeNode.name.equals("add") && invokeNode.owner.equals("java/util/Set") && invokeNode.desc.equals("(Ljava/lang/Object;)Z")) {
+ addMatches++;
+ if(addMatches == 2) {
+ iter.set(new MethodInsnNode(Opcodes.INVOKESTATIC, "org/embeddedt/modernfix/testing/AgentHooks", "addLibraryWithCheck", "(Ljava/util/Set;Ljava/lang/Object;)Z", false));
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
+ node.accept(writer);
+ byte[] finalArray = writer.toByteArray();
+ //dumpDebugClass(className, finalArray);
+ return finalArray;
+ }
+ return classfileBuffer;
+ }
+ });
+ }
+}
diff --git a/test_agent/src/main/java/org/embeddedt/modernfix/testing/AgentHooks.java b/test_agent/src/main/java/org/embeddedt/modernfix/testing/AgentHooks.java
new file mode 100644
index 00000000..05b8de12
--- /dev/null
+++ b/test_agent/src/main/java/org/embeddedt/modernfix/testing/AgentHooks.java
@@ -0,0 +1,17 @@
+package org.embeddedt.modernfix.testing;
+
+import java.nio.file.Path;
+import java.util.Set;
+
+@SuppressWarnings("unused")
+public class AgentHooks {
+ @SuppressWarnings({"unchecked", "rawtypes" })
+ public static boolean addLibraryWithCheck(Set pathSet, Object path) {
+ boolean shouldAdd;
+ if(path instanceof Path) {
+ shouldAdd = !((Path)path).toString().contains("minecraft-merged");
+ } else
+ shouldAdd = true;
+ return shouldAdd && pathSet.add(path);
+ }
+}