diff --git a/.gitignore b/.gitignore index daeb788019..e604323d64 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .gradle/ *-merged.jar +*-mapped.jar *.DS_Store build/ .idea/ diff --git a/build.gradle b/build.gradle index 78bb78370f..9ffa3b70e9 100644 --- a/build.gradle +++ b/build.gradle @@ -10,9 +10,13 @@ buildscript { classpath "net.fabricmc:weave:+" classpath "commons-io:commons-io:1.4" classpath "com.google.guava:guava:19.0" + classpath 'de.undercouch:gradle-download-task:3.4.3' + classpath 'net.fabricmc:tiny-remapper:+' } } +apply plugin: 'de.undercouch.download' + def minecraft_version = "18w43c" def pomfVersion = "${minecraft_version}" @@ -22,6 +26,15 @@ if (ENV.BUILD_NUMBER) { pomfVersion = pomfVersion + "." + "${System.getenv().BUILD_NUMBER}" } +def mappingsDir = file("mappings") +def cacheFilesMinecraft = file(".gradle/minecraft") +def mergedFile = file("${minecraft_version}-merged.jar") +def mappedFile = file("${minecraft_version}-mapped.jar") +def versionFile = new File(cacheFilesMinecraft, "${minecraft_version}.json") +def clientJar = new File(cacheFilesMinecraft, "${minecraft_version}-client.jar") +def serverJar = new File(cacheFilesMinecraft, "${minecraft_version}-server.jar") +def libraries = new File(cacheFilesMinecraft, "${minecraft_version}-libraries") + import groovy.json.JsonSlurper import org.apache.commons.io.FileUtils import com.google.common.hash.HashCode @@ -30,12 +43,17 @@ import com.google.common.io.Files import net.fabricmc.weave.merge.JarMerger import net.fabricmc.weave.CommandTinyify import net.fabricmc.weave.CommandFindMappingErrors +import net.fabricmc.tinyremapper.OutputConsumerPath +import net.fabricmc.tinyremapper.TinyRemapper +import net.fabricmc.tinyremapper.TinyUtils import groovy.util.XmlSlurper +import groovy.io.FileType import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.zip.GZIPOutputStream; import java.io.File; +import java.nio.file.Paths; boolean validateChecksum(File file, String checksum) { if (file != null) { @@ -49,25 +67,65 @@ boolean validateChecksum(File file, String checksum) { return false } -task download << { - def cacheFiles = new File(".gradle/minecraft") - if (!cacheFiles.exists()) cacheFiles.mkdirs() +task downloadVersionsManifest { + //inputs.property "mc_ver", minecraft_version + inputs.property "currenttime", new Date() + def manifestFile = new File(cacheFilesMinecraft, "version_manifest.json") + outputs.file(manifestFile) + doLast { + logger.lifecycle(":downloading minecraft versions manifest") + FileUtils.copyURLToFile(new URL("https://launchermeta.mojang.com/mc/game/version_manifest.json"), manifestFile) + } +} - def manifestFile = new File(cacheFiles, "version_manifest.json") +def getManifestVersion(File manifestFile, String minecraft_version) { + def manifest = manifestFile.exists() ? new JsonSlurper().parseText(FileUtils.readFileToString(manifestFile)) : null + return manifest != null ? manifest.versions.stream().filter({it.id.equals(minecraft_version)}).findFirst() : java.util.Optional.empty() +} - logger.lifecycle(":downloading minecraft json") - FileUtils.copyURLToFile(new URL("https://launchermeta.mojang.com/mc/game/version_manifest.json"), manifestFile) +task downloadWantedVersionManifest(dependsOn: downloadVersionsManifest) { + def manifestFile = downloadVersionsManifest.outputs.files.singleFile + def manifestVersion = getManifestVersion(manifestFile, minecraft_version) - def manifest = new JsonSlurper().parseText(FileUtils.readFileToString(manifestFile)) - def manifestVersion = manifest.versions.stream().filter({ it.id.equals(minecraft_version) }).findFirst() - if (manifestVersion.isPresent()) { + //have to grab the release time as there's a current timestamp on each element?! + inputs.property "releaseTime", manifestVersion.isPresent() ? manifestVersion.get().releaseTime : -1 - def versionFile = new File(cacheFiles, "${minecraft_version}.json") - FileUtils.copyURLToFile(new URL(manifestVersion.get().url), versionFile) + outputs.file versionFile + + doLast { + manifestVersion = getManifestVersion(manifestFile, minecraft_version) //nb need to re-read here in case it didn't exist before + if (manifestVersion.isPresent() || versionFile.exists()) { + + if (manifestVersion.isPresent()) { + FileUtils.copyURLToFile(new URL(manifestVersion.get().url), versionFile) + } + } else { + throw new RuntimeException("No version data for Minecraft version ${minecraft_version}") + } + } + +} + +task downloadMcJars(dependsOn: downloadWantedVersionManifest) { + + inputs.files versionFile + + outputs.files(clientJar, serverJar) + + outputs.upToDateWhen { + def version = new JsonSlurper().parseText(FileUtils.readFileToString(versionFile)) + return clientJar.exists() && serverJar.exists() && validateChecksum(clientJar, version.downloads.client.sha1) && validateChecksum(serverJar, version.downloads.server.sha1) + } + + doLast { + if (!versionFile.exists()) { + throw new RuntimeException("Can't download the jars without the ${versionFile.name} file!") + } + + //reload in case it changed def version = new JsonSlurper().parseText(FileUtils.readFileToString(versionFile)) - def clientJar = new File(cacheFiles, "${minecraft_version}-client.jar") - def serverJar = new File(cacheFiles, "${minecraft_version}-server.jar") + logger.lifecycle(":downloading minecraft jars") if (!clientJar.exists() || !validateChecksum(clientJar, version.downloads.client.sha1)) { logger.lifecycle(":downloading minecraft client") @@ -78,20 +136,17 @@ task download << { logger.lifecycle(":downloading minecraft server") FileUtils.copyURLToFile(new URL(version.downloads.server.url), serverJar) } - - } else { - throw new RuntimeException("No version data for Minecraft version ${minecraft_version}") } } -task mergeJars << { - def mergedFile = new File("${minecraft_version}-merged.jar") +task mergeJars(dependsOn: downloadMcJars) { + inputs.files downloadMcJars.outputs.files.files + outputs.file(mergedFile) - if (!mergedFile.exists()) { - def cacheFiles = new File(".gradle/minecraft") - - def client = new FileInputStream(new File(cacheFiles, "${minecraft_version}-client.jar")) - def server = new FileInputStream(new File(cacheFiles, "${minecraft_version}-server.jar")) + doLast { + logger.lifecycle(":merging jars") + def client = new FileInputStream(inputs.files.files.find {it.name.endsWith("-client.jar")}) + def server = new FileInputStream(inputs.files.files.find {it.name.endsWith("-server.jar")}) def merged = new FileOutputStream(mergedFile) def jarMerger = new JarMerger(client, server, merged) @@ -104,90 +159,176 @@ task mergeJars << { } } -tasks.mergeJars.dependsOn "download" -task setupPomf << { +task setupPomf(dependsOn: mergeJars) { } -tasks.setupPomf.dependsOn "mergeJars" -task pomf << { - def cacheFiles = new File(".gradle/enigma") - if (!cacheFiles.exists()) cacheFiles.mkdirs() +task pomf(dependsOn: setupPomf) { + doLast { + def cacheFilesEnigma = new File(".gradle/enigma") + if (!cacheFilesEnigma.exists()) { + cacheFilesEnigma.mkdirs() + } - def mavenMetadata = new File(cacheFiles, "maven-metadata.xml") + def mavenMetadata = new File(cacheFilesEnigma, "maven-metadata.xml") + def localEnigmaVersion = mavenMetadata.exists() ? new XmlSlurper().parseText(FileUtils.readFileToString(mavenMetadata)).versioning.release : "" - logger.lifecycle(":downloading enigma metadata") - FileUtils.copyURLToFile(new URL("http://maven.modmuss50.me/cuchaz/enigma/maven-metadata.xml"), mavenMetadata) + logger.lifecycle(":downloading enigma metadata") + FileUtils.copyURLToFile(new URL("http://maven.modmuss50.me/cuchaz/enigma/maven-metadata.xml"), mavenMetadata) - def metadata = new XmlSlurper().parseText(FileUtils.readFileToString(mavenMetadata)) - def enigmaVersion = metadata.versioning.release + def metadata = new XmlSlurper().parseText(FileUtils.readFileToString(mavenMetadata)) + def enigmaVersion = metadata.versioning.release - def enigma = new File(cacheFiles, "${enigmaVersion}.jar") + def enigma = new File(cacheFilesEnigma, "${enigmaVersion}.jar") - logger.lifecycle(":downloading enigma") - FileUtils.copyURLToFile(new URL("http://maven.modmuss50.me/cuchaz/enigma/${enigmaVersion}/enigma-${enigmaVersion}-all.jar"), enigma) + if (localEnigmaVersion != enigmaVersion || !enigma.exists()) { + logger.lifecycle(":downloading enigma") + FileUtils.copyURLToFile(new URL("http://maven.modmuss50.me/cuchaz/enigma/${enigmaVersion}/enigma-${enigmaVersion}-all.jar"), enigma) + } else { + logger.lifecycle(":skipping enigma download") + } - logger.lifecycle(":launching enigma ${enigmaVersion}") - ant.java(jar: enigma.getAbsolutePath(), fork: true, spawn: true) { - arg(value: new File("${minecraft_version}-merged.jar").getAbsolutePath()) - arg(value: new File("mappings/").getAbsolutePath()) + logger.lifecycle(":launching enigma") + ant.java(jar: enigma.getAbsolutePath(), fork: true, spawn: true) { + arg(value: mergedFile.getAbsolutePath()) + arg(value: mappingsDir.getAbsolutePath()) + } } } -tasks.pomf.dependsOn "setupPomf" task build(type: Zip) { - from "mappings/" + from mappingsDir include "**/*" archiveName "pomf-enigma-${pomfVersion}.zip" destinationDir(file("build/libs")) } -task checkMappings << { - logger.lifecycle(":checking mappings") +task checkMappings { + inputs.dir mappingsDir + doLast { + logger.lifecycle(":checking mappings") - String[] args = [ - new File("${minecraft_version}-merged.jar").getAbsolutePath(), - new File("mappings").getAbsolutePath() - ] + String[] args = [ + mergedFile.getAbsolutePath(), + mappingsDir.getAbsolutePath() + ] - new CommandFindMappingErrors().run(args) + new CommandFindMappingErrors().run(args) + } } -task buildTiny << { - logger.lifecycle(":generating tiny mappings") - - String[] args = [ - new File("${minecraft_version}-merged.jar").getAbsolutePath(), - new File("mappings").getAbsolutePath(), - "mappings.tiny", - "mojang", - "pomf" - ] - - new CommandTinyify().run(args) - - logger.lifecycle(":compressing tiny mappings") +task buildTiny(dependsOn: "mergeJars") { + inputs.dir mappingsDir def libs = new File("build/libs/") - if (!libs.exists()) libs.mkdirs() - - def buffer = new byte[1024] + if (!libs.exists()) { + libs.mkdirs() + } def outputFile = new File(libs, "pomf-tiny-${pomfVersion}.gz") - def fileOutputStream = new FileOutputStream(outputFile) - def outputStream = new GZIPOutputStream(fileOutputStream) - def inputFile = new File("mappings.tiny") - def fileInputStream = new FileInputStream(inputFile) + outputs.file(outputFile) + doLast { + logger.lifecycle(":generating tiny mappings") - def length - while ((length = fileInputStream.read(buffer)) > 0) { - outputStream.write(buffer, 0, length) + String[] args = [ + mergedFile.getAbsolutePath(), + mappingsDir.getAbsolutePath(), + "mappings.tiny", + "mojang", + "pomf" + ] + + new CommandTinyify().run(args) + + logger.lifecycle(":compressing tiny mappings") + + def buffer = new byte[1024] + def fileOutputStream = new FileOutputStream(outputFile) + def outputStream = new GZIPOutputStream(fileOutputStream) + def inputFile = new File("mappings.tiny") + def fileInputStream = new FileInputStream(inputFile) + + def length + while ((length = fileInputStream.read(buffer)) > 0) { + outputStream.write(buffer, 0, length) + } + + fileInputStream.close() + outputStream.finish() + outputStream.close() + inputFile.delete() + } +} + +tasks.build.dependsOn "buildTiny" + +task downloadMcLibs(dependsOn: downloadWantedVersionManifest) { + inputs.files versionFile + + outputs.file(libraries) + + outputs.upToDateWhen { + return true } - fileInputStream.close() - outputStream.finish() - outputStream.close() - inputFile.delete() + doLast { + if (!versionFile.exists()) { + throw new RuntimeException("Can't download the jars without the ${versionFile.name} file!") + } + + def version = new JsonSlurper().parseText(FileUtils.readFileToString(versionFile)) + + logger.lifecycle(":downloading minecraft libraries") + + if (!libraries.exists()) { + libraries.mkdirs() + } + + version.libraries.each { + def downloadUrl = it.downloads.artifact.url + + download { + src downloadUrl + dest new File(libraries, downloadUrl.substring(downloadUrl.lastIndexOf("/") + 1)) + overwrite false + } + } + } } -tasks.buildTiny.dependsOn "mergeJars" -tasks.build.dependsOn "buildTiny" +task mapJar(dependsOn: [downloadMcLibs, build]) { + inputs.files downloadMcLibs.outputs.files.files + outputs.file(mappedFile) + + doLast { + logger.lifecycle(":mapping minecraft") + + if (mappedFile.exists()) { + mappedFile.delete() + } + + def tinyInput = new File("build/libs/pomf-tiny-${pomfVersion}.gz").toPath() + + def remapper = TinyRemapper.newRemapper() + .withMappings(TinyUtils.createTinyMappingProvider(tinyInput, "mojang", "pomf")) + .build() + + try { + + def outputConsumer = new OutputConsumerPath(mappedFile.toPath()) + + outputConsumer.addNonClassFiles(mergedFile.toPath()) + remapper.read(mergedFile.toPath()) + + libraries.eachFileRecurse(FileType.FILES) {file -> + remapper.read(file.toPath()) + } + + remapper.apply(mergedFile.toPath(), outputConsumer) + outputConsumer.finish() + remapper.finish() + } catch (Exception e) { + remapper.finish(); + throw new RuntimeException("Failed to remap jar", e); + } + } +} \ No newline at end of file