Add custom agent to work around https://github.com/FabricMC/fabric-loader/issues/817
This commit is contained in:
parent
e023829310
commit
03b2395782
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -5,6 +5,7 @@ media
|
||||||
classes/
|
classes/
|
||||||
.architectury-transformer/
|
.architectury-transformer/
|
||||||
fabric/fabricloader.log
|
fabric/fabricloader.log
|
||||||
|
fabric/test_run
|
||||||
|
|
||||||
# Changelog
|
# Changelog
|
||||||
CHANGELOG.md
|
CHANGELOG.md
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ allprojects {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
configure(subprojects.findAll {it.name == "common" || it.name == "forge" || it.name == "fabric"}) {
|
||||||
apply plugin: "dev.architectury.loom"
|
apply plugin: "dev.architectury.loom"
|
||||||
|
|
||||||
loom {
|
loom {
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,10 @@ configurations {
|
||||||
|
|
||||||
include.extendsFrom modIncludeImplementation
|
include.extendsFrom modIncludeImplementation
|
||||||
modImplementation.extendsFrom modIncludeImplementation
|
modImplementation.extendsFrom modIncludeImplementation
|
||||||
|
|
||||||
|
testAgent {
|
||||||
|
canBeConsumed = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
@ -51,10 +55,22 @@ dependencies {
|
||||||
testImplementation("org.assertj:assertj-core:3.19.0")
|
testImplementation("org.assertj:assertj-core:3.19.0")
|
||||||
testImplementation("com.google.guava:guava-testlib:21.0")
|
testImplementation("com.google.guava:guava-testlib:21.0")
|
||||||
testImplementation("org.mockito:mockito-junit-jupiter:5.3.1")
|
testImplementation("org.mockito:mockito-junit-jupiter:5.3.1")
|
||||||
|
|
||||||
|
testAgent(project("path": ":test_agent", "configuration": "agentJar"))
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
useJUnitPlatform()
|
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 {
|
processResources {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ pluginManagement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
include("test_agent")
|
||||||
include("common")
|
include("common")
|
||||||
include("fabric")
|
include("fabric")
|
||||||
include("forge")
|
include("forge")
|
||||||
|
|
|
||||||
86
test_agent/build.gradle
Normal file
86
test_agent/build.gradle
Normal file
|
|
@ -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'
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -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 <a href="https://github.com/FabricMC/fabric-loader/issues/817">issue #817</a>
|
||||||
|
* 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("<init>")) {
|
||||||
|
ListIterator<AbstractInsnNode> 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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user