buildscript { repositories { jcenter() maven { name "Modmuss50 Repository" url 'https://maven.modmuss50.me' } } dependencies { classpath "net.fabricmc:weave:0.2.0.+" classpath "net.fabricmc:stitch:0.1.0.+" 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}" def ENV = System.getenv() 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 import com.google.common.hash.Hashing import com.google.common.io.Files import net.fabricmc.stitch.merge.JarMerger import net.fabricmc.tinyremapper.OutputConsumerPath import net.fabricmc.tinyremapper.TinyRemapper import net.fabricmc.tinyremapper.TinyUtils import net.fabricmc.weave.CommandTinyify import net.fabricmc.weave.CommandFindMappingErrors 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) { def hash = Files.hash(file, Hashing.sha1()) def builder = new StringBuilder() hash.asBytes().each { builder.append(Integer.toString((it & 0xFF) + 0x100, 16).substring(1)) } return builder.toString().equals(checksum) } return false } 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 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() } task downloadWantedVersionManifest(dependsOn: downloadVersionsManifest) { def manifestFile = downloadVersionsManifest.outputs.files.singleFile def manifestVersion = getManifestVersion(manifestFile, minecraft_version) //have to grab the release time as there's a current timestamp on each element?! inputs.property "releaseTime", manifestVersion.isPresent() ? manifestVersion.get().releaseTime : -1 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)) logger.lifecycle(":downloading minecraft jars") if (!clientJar.exists() || !validateChecksum(clientJar, version.downloads.client.sha1)) { logger.lifecycle(":downloading minecraft client") FileUtils.copyURLToFile(new URL(version.downloads.client.url), clientJar) } if (!serverJar.exists() || !validateChecksum(serverJar, version.downloads.server.sha1)) { logger.lifecycle(":downloading minecraft server") FileUtils.copyURLToFile(new URL(version.downloads.server.url), serverJar) } } } task mergeJars(dependsOn: downloadMcJars) { inputs.files downloadMcJars.outputs.files.files outputs.file(mergedFile) 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) jarMerger.merge() jarMerger.close() client.close() server.close() merged.close() } } task setupPomf(dependsOn: mergeJars) { } task pomf(dependsOn: setupPomf) { doLast { def cacheFilesEnigma = new File(".gradle/enigma") if (!cacheFilesEnigma.exists()) { cacheFilesEnigma.mkdirs() } 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) def metadata = new XmlSlurper().parseText(FileUtils.readFileToString(mavenMetadata)) def enigmaVersion = metadata.versioning.release def enigma = new File(cacheFilesEnigma, "${enigmaVersion}.jar") 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") ant.java(jar: enigma.getAbsolutePath(), fork: true, spawn: true) { arg(value: mergedFile.getAbsolutePath()) arg(value: mappingsDir.getAbsolutePath()) } } } task build(type: Zip) { from mappingsDir include "**/*" archiveName "pomf-enigma-${pomfVersion}.zip" destinationDir(file("build/libs")) } task checkMappings { inputs.dir mappingsDir doLast { logger.lifecycle(":checking mappings") String[] args = [ mergedFile.getAbsolutePath(), mappingsDir.getAbsolutePath() ] new CommandFindMappingErrors().run(args) } } task buildTiny(dependsOn: "mergeJars") { inputs.dir mappingsDir def libs = new File("build/libs/") if (!libs.exists()) { libs.mkdirs() } def outputFile = new File(libs, "pomf-tiny-${pomfVersion}.gz") outputs.file(outputFile) doLast { logger.lifecycle(":generating tiny mappings") 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 } 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 } } } } task mapJar(dependsOn: [downloadMcLibs, build]) { inputs.files downloadMcLibs.outputs.files.files outputs.file(mappedFile) //Force the task to always run outputs.upToDateWhen { return true } 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); } } }