yarn/build.gradle

459 lines
12 KiB
Groovy

buildscript {
repositories {
jcenter()
maven {
name "Modmuss50 Repository"
url 'https://maven.modmuss50.me'
}
}
dependencies {
classpath "net.fabricmc:weave:0.3.0.+"
classpath "net.fabricmc:stitch:0.1.2.46"
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:+'
}
}
plugins {
id 'de.undercouch.download' version '3.4.3'
id 'maven'
id 'maven-publish'
}
def minecraft_version = "1.14 Pre-Release 2"
def ENV = System.getenv()
// Fetch build number from Jenkins
def build_number = ENV.BUILD_NUMBER ?: "local"
def yarnVersion = "${minecraft_version}+build.$build_number"
repositories {
mavenCentral()
maven {
name "Modmuss50 Repository"
url 'https://maven.modmuss50.me'
}
}
configurations {
enigmaRuntime {
resolutionStrategy {
cacheDynamicVersionsFor 0, "seconds"
cacheChangingModulesFor 0, "seconds"
}
}
}
dependencies {
enigmaRuntime "net.fabricmc:stitch:0.1.1.39+"
enigmaRuntime "cuchaz:enigma:0.13.1.+:all"
}
def mappingsDir = file("mappings")
def cacheFilesMinecraft = file(".gradle/minecraft")
def tempDir = file(".gradle/temp")
def mergedFile = file("${minecraft_version}-merged.jar")
def intermediaryJar = file("${minecraft_version}-intermediary.jar")
def namedJar = file("${minecraft_version}-named.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")
def libs = new File("build/libs/")
import groovy.json.JsonSlurper
import org.apache.commons.io.FileUtils
import com.google.common.hash.Hashing
import com.google.common.io.Files
import net.fabricmc.stitch.commands.CommandMergeTiny
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.io.FileType
import java.util.zip.GZIPOutputStream
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 = inputs.files.files.find {it.name.endsWith("-client.jar")}
def server = inputs.files.files.find {it.name.endsWith("-server.jar")}
def merged = mergedFile
if(merged.exists()){
return
}
def jarMerger = new JarMerger(client, server, merged)
jarMerger.merge()
jarMerger.close()
}
}
task setupYarn(dependsOn: mergeJars) {
}
task yarn(dependsOn: setupYarn) {
doLast {
ant.java(
classname: 'cuchaz.enigma.Main',
classpath: configurations.enigmaRuntime.asPath,
fork: true,
spawn: true
) {
jvmarg(value: "-Xmx2048m")
arg(value: mergedFile.getAbsolutePath())
arg(value: mappingsDir.getAbsolutePath())
}
}
}
task buildEnigma(type: Zip) {
from mappingsDir
include "**/*"
archiveName "yarn-enigma-${yarnVersion}.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 downloadIntermediary(type: Download){
def url = "https://github.com/FabricMC/intermediary/raw/master/mappings/${minecraft_version}.tiny"
src url.replaceAll(" ", "%20")
dest new File(cacheFilesMinecraft, "${minecraft_version}-intermediary.tiny")
}
task buildYarnTiny(dependsOn: "mergeJars",type: FileOutput) {
inputs.dir mappingsDir
if (!libs.exists()) {
libs.mkdirs()
}
def yarnTiny = new File(tempDir, "yarn-mappings.tiny")
fileOutput = yarnTiny
outputs.upToDateWhen {return false}
doLast {
logger.lifecycle(":generating tiny mappings")
String[] args = [
mergedFile.getAbsolutePath(),
mappingsDir.getAbsolutePath(),
yarnTiny.getAbsolutePath(),
"official",
"named"
]
new CommandTinyify().run(args)
}
}
task mergeTiny(dependsOn: ["buildYarnTiny", "downloadIntermediary"], type: FileOutput) {
def yarnTinyInput = buildYarnTiny.fileOutput
def intermediaryTinyInput = downloadIntermediary.dest
def outputFile = new File(tempDir, "mappings.tiny")
outputs.file(outputFile)
fileOutput = outputFile
outputs.upToDateWhen {return false}
doLast {
logger.lifecycle(":merging yarn and intermediary")
String[] args = [
yarnTinyInput.getAbsolutePath(),
intermediaryTinyInput.getAbsolutePath(),
outputFile.getAbsolutePath(),
"intermediary",
"official"
]
new CommandMergeTiny().run(args)
}
}
task tinyJar(type: Jar, dependsOn: "mergeTiny") {
outputs.upToDateWhen {return false}
archiveName = "yarn-${yarnVersion}.jar"
destinationDir(file("build/libs"))
classifier = ""
from (mergeTiny.fileOutput) {
rename { "mappings/mappings.tiny" }
}
}
task compressTiny(dependsOn: ["tinyJar", "mergeTiny"], type: FileOutput){
def outputFile = new File(libs, "yarn-tiny-${yarnVersion}.gz")
outputs.file(outputFile)
fileOutput = outputFile
def inputFile = mergeTiny.fileOutput
outputs.upToDateWhen {return false}
doLast {
logger.lifecycle(":compressing tiny mappings")
def buffer = new byte[1024]
def fileOutputStream = new FileOutputStream(outputFile)
def outputStream = new GZIPOutputStream(fileOutputStream)
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()
}
}
clean.doFirst {
delete tempDir, cacheFilesMinecraft
}
tasks.build.dependsOn "compressTiny"
tasks.build.dependsOn "buildEnigma"
tasks.build.dependsOn "tinyJar"
task downloadMcLibs(dependsOn: downloadWantedVersionManifest) {
inputs.files versionFile
outputs.file(libraries)
outputs.upToDateWhen {
return false
}
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 mapIntermediaryJar(dependsOn: [downloadMcLibs, build]) {
inputs.files downloadMcLibs.outputs.files.files
outputs.file(intermediaryJar)
//Force the task to always run
outputs.upToDateWhen {
return false
}
doLast {
logger.lifecycle(":mapping minecraft to intermdiary")
def tinyInput = new File("build/libs/yarn-tiny-${yarnVersion}.gz")
mapJar(intermediaryJar, mergedFile, tinyInput, libraries, "official", "intermediary")
}
}
task mapNamedJar(dependsOn: mapIntermediaryJar) {
inputs.files downloadMcLibs.outputs.files.files
outputs.file(namedJar)
//Force the task to always run
outputs.upToDateWhen {
return false
}
doLast {
logger.lifecycle(":mapping minecraft to named")
def tinyInput = new File("build/libs/yarn-tiny-${yarnVersion}.gz")
mapJar(namedJar, intermediaryJar, tinyInput, libraries, "intermediary", "named")
}
}
publishing {
publications {
maven(MavenPublication) {
groupId 'net.fabricmc'
artifactId "yarn"
version yarnVersion
artifact (compressTiny.fileOutput) {
classifier "tiny"
builtBy compressTiny
}
artifact (buildEnigma) {
classifier "enigma"
}
artifact (tinyJar)
}
}
repositories {
maven {
url "http://mavenupload.modmuss50.me/"
if (project.hasProperty('mavenPass')) {
credentials {
username 'buildslave'
password project.getProperty('mavenPass')
}
}
}
}
}
void mapJar(File output, File input, File mappings, File libraries, String from, String to){
if (output.exists()) {
output.delete()
}
def remapper = TinyRemapper.newRemapper()
.withMappings(TinyUtils.createTinyMappingProvider(mappings.toPath(), from, to))
.renameInvalidLocals(true)
.rebuildSourceFilenames(true)
.build()
try {
def outputConsumer = new OutputConsumerPath(output.toPath())
outputConsumer.addNonClassFiles(input.toPath())
remapper.readInputs(input.toPath())
libraries.eachFileRecurse(FileType.FILES) {file ->
remapper.readClassPath(file.toPath())
}
remapper.apply(outputConsumer)
outputConsumer.close()
remapper.finish()
} catch (Exception e) {
remapper.finish()
throw new RuntimeException("Failed to remap jar", e);
}
}
class FileOutput extends DefaultTask {
@OutputFile File fileOutput
}