From 9b9587e2346a8c53696ba589ef1f8cfd51e3dc62 Mon Sep 17 00:00:00 2001 From: Sebastian Hartte Date: Fri, 6 Dec 2024 22:48:55 +0100 Subject: [PATCH] Add code to handle old server jar dependencies --- .../GenerateModuleMetadata.groovy | 99 ++++++++++++++++++- 1 file changed, 94 insertions(+), 5 deletions(-) diff --git a/buildSrc/src/main/groovy/net/neoforged/minecraftdependencies/GenerateModuleMetadata.groovy b/buildSrc/src/main/groovy/net/neoforged/minecraftdependencies/GenerateModuleMetadata.groovy index 30f3852..acc34a3 100644 --- a/buildSrc/src/main/groovy/net/neoforged/minecraftdependencies/GenerateModuleMetadata.groovy +++ b/buildSrc/src/main/groovy/net/neoforged/minecraftdependencies/GenerateModuleMetadata.groovy @@ -4,11 +4,18 @@ import groovy.json.JsonOutput import groovy.json.JsonSlurper import groovy.transform.CompileStatic import org.gradle.api.DefaultTask +import org.gradle.api.GradleException import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.Property -import org.gradle.api.tasks.* +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.PathSensitive +import org.gradle.api.tasks.PathSensitivity +import org.gradle.api.tasks.TaskAction import javax.inject.Inject +import java.util.jar.JarInputStream import java.util.zip.ZipFile @CompileStatic @@ -163,6 +170,42 @@ abstract class GenerateModuleMetadata extends DefaultTask implements HasMinecraf private static final List platforms = ["windows", "osx", "linux"] + private Set getDirectoryListing(String artifactId) { + var listingFile = new File(temporaryDir, artifactId.replace(':', '-') + ".txt") + if (listingFile.exists()) { + return new HashSet<>(listingFile.readLines()) + } + + var parts = artifactId.split(":") + String relativeUrl + if (parts.length == 3) { + relativeUrl = parts[0].replace('.', '/') + "/" + parts[1] + "/" + parts[2] + "/" + parts[1] + "-" + parts[2] + ".jar" + } else { + relativeUrl = parts[0].replace('.', '/') + "/" + parts[1] + "/" + parts[2] + "/" + parts[1] + "-" + parts[2] + "-" + parts[3] + ".jar" + } + var url = URI.create("https://libraries.minecraft.net/" + relativeUrl).toURL() + println("Getting $url") + var folders = new HashSet() + url.openStream().with { input -> + var jin = new JarInputStream(input) + for (var entry = jin.nextJarEntry; entry != null; entry = jin.nextJarEntry) { + if (!entry.name.startsWith("META-INF/") && entry.name.contains("/") && !entry.name.endsWith("/")) { + folders.add(entry.name.substring(0, entry.name.lastIndexOf('/'))) + } + } + } + + println("Found ${folders.size()} folders in jar") + + try (var writer = listingFile.newWriter()) { + for (var folder in folders) { + writer.writeLine(folder) + } + } + + return folders + } + private void getMcDeps(List server, List client, Map> clientNatives) { Map metaJson = new JsonSlurper().parse(meta.get().asFile) as Map (metaJson.libraries as List>).each { Map lib -> @@ -188,15 +231,61 @@ abstract class GenerateModuleMetadata extends DefaultTask implements HasMinecraf } } try (def zf = new ZipFile(serverJar.get().getAsFile())) { - def entry = zf.getEntry('META-INF/libraries.list') - if (entry != null) { - try (def is = zf.getInputStream(entry)) { + def librariesListEntry = zf.getEntry('META-INF/libraries.list') + if (librariesListEntry != null) { + try (def is = zf.getInputStream(librariesListEntry)) { is.readLines().each { server.add(it.split('\t')[1]) } } } else { - throw new RuntimeException("Could not find libraries.list inside of server.jar") + // This will be slow. + + // List all directories found in the server jar + var dirnames = new HashSet(); + zf.entries().iterator().each { + if (it.name.contains("/") && !it.name.endsWith("/")) { + var dirname = it.name.substring(0, it.name.lastIndexOf('/')) + if ( + // the annotation packages are re-added by NeoForm/MCP anyway and are not required to run or compile against the code + dirname != "javax/annotation" + && dirname != "javax/annotation/concurrent" + && dirname != "javax/annotation/meta" + && !dirname.startsWith("net/minecraft/") + && !dirname.startsWith("data/") + && !dirname.startsWith("assets/") + && dirname != "assets" + && dirname != "data" + && dirname != "META-INF" + && !dirname.startsWith("META-INF/")) { + dirnames.add(dirname) + } + } + } + + var mappedDirnames = new HashSet() + var libraries = new LinkedHashSet() + + // For each client library, find the list of folders contained within + // We need to do this in order of the declared libraries since mojang chose to fix log4j2 issues + // by introducing a higherpriority library that contains files from log4j2 and netty + for (var artifactId in client) { + var folderListing = getDirectoryListing(artifactId) + for (var folder in folderListing) { + if (dirnames.contains(folder)) { + libraries.add(artifactId) + mappedDirnames.add(folder) + } + } + } + + // Now report any directories in the server jar we could NOT map to a library + dirnames.removeAll(mappedDirnames) + if (!dirnames.isEmpty()) { + throw new GradleException("Couldn't map the following directories from the server jar to libraries: " + dirnames) + } + + server.addAll(libraries) } } }