ForgePatch/build.gradle

759 lines
28 KiB
Groovy

buildscript {
repositories {
mavenLocal()
maven { url = 'http://files.minecraftforge.net/maven' }
jcenter()
mavenCentral()
}
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:3.+'
}
}
import groovy.json.JsonSlurper
import groovy.json.JsonBuilder
import java.text.SimpleDateFormat
import java.util.Date
import java.security.MessageDigest
import java.net.URL
import net.minecraftforge.gradle.common.task.DownloadMavenArtifact
import net.minecraftforge.gradle.common.task.SignJar
import org.apache.tools.ant.filters.ReplaceTokens
import de.undercouch.gradle.tasks.download.Download
plugins {
id 'net.minecrell.licenser' version '0.4'
id 'org.ajoberstar.grgit' version '2.3.0'
id 'de.undercouch.download' version '3.3.0'
}
apply plugin: 'eclipse'
group = 'net.minecraftforge'
version = '1.0.0'
project(':mcp') {
apply plugin: 'net.minecraftforge.gradle.forgedev.mcp'
mcp {
config = '1.13-2018.09.12.04.11.00'
pipeline = 'joined'
}
}
project(':clean') {
evaluationDependsOn(':mcp')
apply plugin: 'eclipse'
apply plugin: 'net.minecraftforge.gradle.forgedev.patcher'
repositories {
mavenCentral()
}
patcher {
parent = project(':mcp')
patchedSrc = file('src/main/java')
mappings channel: 'snapshot', version: '20180921-1.13'
mcVersion = '1.13'
}
task runclient(type: JavaExec) {
doFirst {
mkdir 'runclient'
}
classpath sourceSets.main.runtimeClasspath
args = ['--accessToken', '0', '--version', '1.13']
main 'net.minecraft.client.main.Main'
workingDir 'runclient'
}
}
project(':forge') {
evaluationDependsOn(':clean')
apply plugin: 'java-library'
apply plugin: 'maven-publish'
apply plugin: 'eclipse'
apply plugin: 'net.minecraftforge.gradle.forgedev.patcher'
apply plugin: 'net.minecrell.licenser'
apply plugin: 'de.undercouch.download'
compileJava.sourceCompatibility = compileJava.targetCompatibility = sourceCompatibility = targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
sourceSets {
main {
java {
srcDir "$rootDir/src/main/java"
}
resources {
srcDir "$rootDir/src/main/resources"
}
}
}
repositories {
mavenLocal()
mavenCentral()
}
ext {
MCP_ARTIFACT = project(':mcp').mcp.config
MCP_VERSION = project(':mcp').mcp.config.version.split('-')[1] // The timestamp only.
}
patcher {
parent = project(':clean')
patches = file("$rootDir/patches/minecraft")
patchedSrc = file('src/main/java')
accessTransformer = file("$rootDir/src/main/resources/forge_at.cfg")
exc = file("$rootDir/src/main/resources/forge.exc")
srgPatches = true
srgUniversal = true
clientRun {
main = 'net.minecraftforge.fml.LaunchTesting'
environment = [
target: 'fmldevclient'
]
properties = [
target: 'fmldevclient',
assetDirectory: downloadAssets.output
]
}
serverRun {
main = 'net.minecraftforge.fml.LaunchTesting'
environment = [
target: 'fmldevserver'
]
}
mcVersion = '1.13'
}
group = 'net.minecraftforge'
version = getVersionFromJava(file("$rootDir/src/main/java/net/minecraftforge/common/ForgeVersion.java"), patcher.mcVersion)
applyPatches {
canonicalizeAccess true
canonicalizeWhitespace true
maxFuzz 3
}
dependencies {
api 'net.minecraft:client:1.13:extra'
api 'org.ow2.asm:asm:6.2'
api 'org.ow2.asm:asm-commons:6.2'
api 'org.ow2.asm:asm-tree:6.2'
api 'cpw.mods:modlauncher:0.1.0'
api 'net.minecraftforge:accesstransformers:0.10+:shadowed'
api 'net.minecraftforge:eventbus:0.1+:service'
api 'net.minecraftforge:forgespi:0.1+'
api 'net.minecraftforge:coremods:0.1+'
api 'com.electronwill.night-config:core:3.4.0'
api 'com.electronwill.night-config:toml:3.4.0'
api 'org.jline:jline:3.5.1'
api 'org.apache.maven:maven-artifact:3.5.3'
api 'java3d:vecmath:1.5.2'
}
task runclient(type: JavaExec, dependsOn: [":forge:downloadAssets", ":forge:extractNatives"]) {
doFirst {
mkdir 'runclient'
}
doFirst {
copy {
from sourceSets.main.resources
into "$buildDir/classes/java/main"
}
}
//jvmArgs = ['-verbose:class']
classpath sourceSets.main.runtimeClasspath
main 'net.minecraftforge.fml.LaunchTesting'
systemProperties = [
"org.lwjgl.util.Debug": "true",
"org.lwjgl.util.DebugLoader": "true"
]
environment += [
target:'fmldevclient',
assetDirectory: file("${gradle.getGradleUserHomeDir()}/caches/forge_gradle/assets/"),
nativesDirectory: extractNatives.output
]
workingDir 'runclient'
}
task runserver(type: JavaExec) {
doFirst {
mkdir 'runserver'
}
classpath sourceSets.main.runtimeClasspath
main 'net.minecraftforge.fml.LaunchTesting'
args 'nogui'
environment target:'fmldevserver'
workingDir 'runserver'
}
task ciWriteBuildNumber {
doLast {
def file = file("$rootDir/src/main/java/net/minecraftforge/common/ForgeVersion.java")
def bn = System.getenv('BUILD_NUMBER') ?: project.ext.properties.buildNumber ?: 0
def outfile = ''
file.eachLine{ String s ->
if (s.matches('^ public static final int buildVersion = [\\d]+;\$'))
s = " public static final int buildVersion = ${bn};"
if (s.matches('^ public static final String mcVersion = "[^\\"]+";'))
s = " public static final String mcVersion = \"${patcher.mcVersion}\";"
outfile += (s+'\n')
}
file.write(outfile)
}
}
def extraTxts = [
rootProject.file('CREDITS.txt'),
rootProject.file('LICENSE.txt')
]
/* TODO: Changelog
if (project.hasProperty('forgeJenkinsPass'))
extraTxts += changelog
*/
task downloadCrowdin() {
ext {
output = file('build/crowdin_raw.zip')
update = file('build/crowdin.json')
id = 'minecraft-forge'
}
onlyIf {
project.hasProperty('crowdinKey') && !project.gradle.startParameter.isOffline()
}
doLast {
download {
src "https://api.crowdin.com/api/project/${id}/export?key=${project.crowdinKey}&json"
dest update
overwrite true
}
if (!update.text.contains('success')) {
throw new RuntimeException("Crowdin export failed, see ${update} for more info")
}
download {
src "https://api.crowdin.com/api/project/${id}/download/all.zip?key=${project.crowdinKey}"
dest output
overwrite true
}
}
}
task crowdin(type: Zip) {
dependsOn downloadCrowdin
baseName = project.name
version = project.version
classifier = 'crowdin'
destinationDir = file('build/distributions')
from(zipTree(downloadCrowdin.output)){
eachFile { //Tired of waiting for crowdin API, rename things myself. Remove once crowdin stops being dumb
if (it.name.equals('en_us.json') && !it.path.startsWith('assets/')) {
it.name = it.path.split('/')[0] + '.json'
it.path = 'assets/forge/lang/' + it.name
}
}
exclude { it.isDirectory() }
rename { it.toLowerCase() }//Minecraft needs it lowercase.
exclude '**/*.lang' //Pre-1.13 format
}
}
task launcherJson() {
ext {
output = file('build/libs/version.json')
vanilla = project(':mcp').file('build/mcp/downloadJson/version.json')
timestamp = dateToIso8601(new Date())
comment = [
"Please do not automate the download and installation of Forge.",
"Our efforts are supported by ads from the download page.",
"If you MUST automate this, please consider supporting the project through https://www.patreon.com/LexManos/"
]
}
inputs.file vanilla
outputs.file output
doLast {
def json_vanilla = new JsonSlurper().parseText(vanilla.text)
def json = [
_comment_: comment,
id: project.version.split('-')[0] + '-forge-' + project.version.split('-')[1],
time: timestamp,
releaseTime: timestamp,
type: 'release',
mainClass: 'cpw.mods.modlauncher.Launcher',
inheritsFrom: patcher.mcVersion,
logging: [],
arguments: [
game: json_vanilla.arguments.game + ['--launchTarget', 'fmlclient']
],
libraries: [
[ name: "${project.group}:${project.name}:${project.version}" ]
]
]
//TODO: There should be a way to mark this in the config declaration...
def forge = [
'cpw.mods:modlauncher',
'org.ow2.asm:asm',
'org.ow2.asm:asm-commons',
'org.ow2.asm:asm-tree',
'net.minecraftforge:accesstransformers',
'net.minecraftforge:eventbus',
'net.minecraftforge:forgespi',
'net.minecraftforge:coremods',
'com.electronwill.night-config:core',
'com.electronwill.night-config:toml',
'org.jline:jline',
'org.apache.maven:maven-artifact',
'java3d:vecmath'
]
def mojang = []
def artifacts = getArtifacts(project, project.configurations.compileClasspath)
artifacts.each { key, lib ->
if (forge.contains(key) || mojang.contains(key)){
json.libraries.add(lib)
}
}
output.text = new JsonBuilder(json).toPrettyString()
}
}
task installerJson(dependsOn: [launcherJson, genClientBinPatches]) {
ext {
output = file('build/libs/install_profile.json')
INSTALLER_TOOLS = 'net.minecraftforge:installertools:1.0.3'
}
doFirst {
ext.BIN_PATCHER = 'net.minecraftforge:binarypatcher:' + genClientBinPatches.resolvedVersion
}
inputs.file launcherJson.output
outputs.file output
doLast {
def idx = project.version.indexOf('-')
def libs = [:]
def json = [
_comment_: launcherJson.comment,
profile: project.name,
version: project.version.substring(0, idx) + "-${project.name}" + project.version.substring(idx),
json: '/version.json',
path: "${project.group}:${project.name}:${project.version}:universal",
logo: '/big_logo.png',
minecraft: patcher.mcVersion,
welcome: "Welcome to the simple ${project.name.capitalize()} installer.",
data: [
MAPPINGS: [
client: "[${MCP_ARTIFACT.group}:${MCP_ARTIFACT.name}:${MCP_ARTIFACT.version}:mappings@txt]",
server: "[${MCP_ARTIFACT.group}:${MCP_ARTIFACT.name}:${MCP_ARTIFACT.version}:mappings@txt]"
],
BINPATCH: [
client: '/data/client.lzma',
server: '/data/server.lzma'
],
MC_SLIM: [
client: "[net.minecraft:client:${patcher.mcVersion}:slim]",
server: "[net.minecraft:server:${patcher.mcVersion}:slim]"
],
MC_DATA: [
client: "[net.minecraft:client:${patcher.mcVersion}:data]",
server: "[net.minecraft:server:${patcher.mcVersion}:data]"
],
MC_EXTRA: [
client: "[net.minecraft:client:${patcher.mcVersion}:extra]",
server: "[net.minecraft:server:${patcher.mcVersion}:extra]"
],
MC_SRG: [
client: "[net.minecraft:client:${patcher.mcVersion}-${MCP_VERSION}:srg]",
server: "[net.minecraft:server:${patcher.mcVersion}-${MCP_VERSION}:srg]"
],
PATCHED: [
client: "[${project.group}:${project.name}:${project.version}:client]",
server: "[${project.group}:${project.name}:${project.version}:server]"
]
],
processors: [
[
jar: INSTALLER_TOOLS,
classpath: getClasspath(project, libs, INSTALLER_TOOLS),
args: [
'--task', 'MCP_DATA',
'--input', "[${MCP_ARTIFACT.descriptor}]",
'--output', '{MAPPINGS}',
'--key', 'mappings'
]
], [
jar: 'net.minecraftforge:jarsplitter:1.0.3',
classpath: getClasspath(project, libs, 'net.minecraftforge:jarsplitter:1.0.3'),
args: [
'--input', '{MINECRAFT_JAR}',
'--slim', '{MC_SLIM}',
'--data', '{MC_DATA}',
'--extra', '{MC_EXTRA}',
'--srg', '{MAPPINGS}'
]
], [ // SpecialSource has a bug where it won't create the nessasary directories, remove when they fix that.
jar: INSTALLER_TOOLS,
classpath: getClasspath(project, libs, INSTALLER_TOOLS),
args: [
'--task', 'CREATE_PARENTS',
'--target', '{MC_SRG}'
]
], [
jar: 'net.md-5:SpecialSource:1.8.3',
classpath: getClasspath(project, libs, 'net.md-5:SpecialSource:1.8.3'),
args: [
'--in-jar', '{MC_SLIM}',
'--out-jar', '{MC_SRG}',
'--srg-in', '{MAPPINGS}'
]
], [
jar: BIN_PATCHER,
classpath: getClasspath(project, libs, BIN_PATCHER),
args: [
'--clean', '{MC_SRG}',
'--output', '{PATCHED}',
'--apply', '{BINPATCH}'
]
]
]
]
getClasspath(project, libs, MCP_ARTIFACT.descriptor) //Tell it to download mcp_config
json.libraries = libs.values().sort{a,b -> a.name.compareTo(b.name)}
output.text = new JsonBuilder(json).toPrettyString()
}
}
universalJar {
dependsOn launcherJson
from(launcherJson.output) {
rename { 'version.json' }
}
from extraTxts
/* TODO: Annotation Cache? need to talk to cpw about his new design.
from(fixAnnotationsJson){
into 'META-INF'
}
dependsOn fixAnnotationsJson
*/
// add crowdin locales
from { crowdin.getDidWork() ? zipTree(crowdin.archivePath) : null}
dependsOn crowdin
doFirst {
def json = new JsonSlurper().parseText(launcherJson.output.text)
def classpath = new StringBuilder()
json.libraries.each { lib ->
if (!lib.name.startsWith("${project.group}:${project.name}")) {
// group : artifact : version [: classifier][@extension]
def split = lib.name.split(':')
def ext = 'jar'
if (split[split.length-1].indexOf('@') != -1) {
ext = split[split.length-1].split('@')[1]
split[split.length-1] = split[split.length-1].split('@')[0]
}
def group = split[0].replace('.', '/')
def artifact = split[1]
def version = split[2]
def classifier = split.length > 3 ? split[3] : null
if (classifier == null)
classpath += "libraries/$group/$artifact/$version/$artifact-${version}.${ext} "
else
classpath += "libraries/$group/$artifact/$version/$artifact-${version}-${classifier}.${ext} "
}
}
classpath += "minecraft_server.${patcher.mcVersion}.jar"
manifest.attributes([
"Main-Class": "net.minecraftforge.fml.relauncher.ServerLaunchWrapper",
"TweakClass": "net.minecraftforge.fml.common.launcher.FMLTweaker",
"Class-Path": classpath.toString()
])
}
}
task signUniversal(type: SignJar, dependsOn: universalJar) {
onlyIf {
project.hasProperty('jarsigner') && universalJar.state.failure == null
}
def jarsigner = [:];
if (project.hasProperty('jarsigner'))
jarsigner = project.jarsigner;
alias = 'forge'
storePass = jarsigner.storepass
keyPass = jarsigner.keypass
keyStore = jarsigner.keystore
inputFile = universalJar.archivePath
outputFile = universalJar.archivePath
doFirst {
project.logger.lifecycle('Signing: ' + inputFile)
}
}
universalJar.finalizedBy(signUniversal)
task downloadInstaller(type: DownloadMavenArtifact) {
artifact = 'net.minecraftforge:installer:2.+:shrunk'
}
task installerJar(type: Zip, dependsOn: [downloadInstaller, universalJar, installerJson, launcherJson, genClientBinPatches, genServerBinPatches]) {
classifier = 'installer'
extension = 'jar' //Needs to be Zip task to not override Manifest, so set extension
from(extraTxts)
from(rootProject.file('/src/main/resources/forge_logo.png')) {
rename{'big_logo.png'}
}
from(rootProject.file('/src/main/resources/url.png'))
from(genClientBinPatches.output) {
rename{'data/client.lzma'}
}
from(genServerBinPatches.output) {
rename{'data/server.lzma'}
}
from(universalJar) {
into "/maven/${project.group.replace('.', '/')}/${project.name}/${project.version}/"
}
from(installerJson.output)
from(launcherJson.output)
from(zipTree(downloadInstaller.output)) {
duplicatesStrategy = 'exclude'
}
}
task signInstaller(type: SignJar, dependsOn: installerJar) {
onlyIf {
project.hasProperty('jarsigner') && installerJar.state.failure == null
}
def jarsigner = [:];
if (project.hasProperty('jarsigner'))
jarsigner = project.jarsigner;
alias = 'forge'
storePass = jarsigner.storepass
keyPass = jarsigner.keypass
keyStore = jarsigner.keystore
inputFile = installerJar.archivePath
outputFile = installerJar.archivePath
doFirst {
project.logger.lifecycle('Signing: ' + inputFile)
}
}
signInstaller.finalizedBy(signInstaller)
task makeMdk(type: Zip) {
baseName = project.name
classifier = 'mdk'
version = project.version
destinationDir = file('build/distributions')
from rootProject.file('gradlew')
from rootProject.file('gradlew.bat')
from extraTxts
from(rootProject.file('gradle/')){
into('gradle/')
}
from(rootProject.file('mdk/')){
/* filter(ReplaceTokens, tokens: [
VERSION: project.version
])
*/
rename 'gitignore\\.txt', '.gitignore'
}
}
license {
header = file("$rootDir/LICENSE-header.txt")
include 'net/minecraftforge/'
exclude 'net/minecraftforge/server/terminalconsole/'
exclude 'net/minecraftforge/api/' // exclude API here because it's validated in the SPI build
exclude 'net/minecraftforge/fml/common/versioning/ComparableVersion.java'
exclude 'net/minecraftforge/fml/common/versioning/InvalidVersionSpecificationException.java'
exclude 'net/minecraftforge/fml/common/versioning/Restriction.java'
exclude 'net/minecraftforge/fml/common/versioning/VersionRange.java'
tasks {
main {
files = files("$rootDir/src/main/java")
}
test {
files = files("$rootDir/src/test/java")
}
}
}
publishing {
publications {
mavenJava(MavenPublication) {
artifact universalJar
//TODO: changelog
//TODO: installer
//TODO: installer-win
artifact makeMdk
artifact userdevJar
pom {
name = 'forge'
description = 'Modifactions to Minecraft to enable mod developers.'
url = 'https://github.com/MinecraftForge/MinecraftForge'
scm {
url = 'https://github.com/MinecraftForge/MinecraftForge'
connection = 'scm:git:git://github.com/MinecraftForge/MinecraftForge.git'
developerConnection = 'scm:git:git@github.com:MinecraftForge/MinecraftForge.git'
}
issueManagement {
system = 'github'
url = 'https://github.com/MinecraftForge/MinecraftForge/issues'
}
licenses {
license {
name = 'LGPL 2.1'
url = 'https://github.com/MinecraftForge/MinecraftForge/blob/1.13-pre/LICENSE.txt'
distribution = 'repo'
}
}
}
}
}
repositories {
maven {
if (project.hasProperty('forgeMavenPassword')) {
credentials {
username project.properties.forgeMavenUser
password project.properties.forgeMavenPassword
}
url 'http://files.minecraftforge.net/maven/manage/upload'
} else {
url 'file://' + rootProject.file('repo').getAbsolutePath()
}
}
}
}
}
def getVersionFromJava(def file, def mcver) {
def major, minor, revision, build = '0'
def prefix = 'public static final int'
file.eachLine{ String s ->
s = s.trim()
if (s.startsWith(prefix)) {
s = s.substring(prefix.length(), s.length() - 1)
s = s.replace('=', ' ').replace('Version', '').replaceAll(' +', ' ').trim()
String[] pts = s.split(' ')
if (pts[0].equals('major')) major = pts[pts.length - 1]
else if (pts[0] == 'minor') minor = pts[pts.length - 1]
else if (pts[0] == 'revision') revision = pts[pts.length - 1]
}
}
build = System.getenv('BUILD_NUMBER') ?: project.ext.properties.buildNumber ?: 0
String branch = null
if (!System.getenv().containsKey('GIT_BRANCH')) {
branch = grgit.branch.current().name
} else {
branch = System.getenv('GIT_BRANCH')
branch = branch.substring(branch.lastIndexOf('/') + 1)
}
def out = "${mcver.replace('-', '_')}-$major.$minor.$revision.$build"
if (branch && branch != 'master' && branch != 'HEAD' && branch != mcver && branch != mcver + '.0') {
if (!(branch.endsWith('.x') && mcver.startsWith(branch.substring(0, branch.length() -2))))
out += "-$branch"
}
return out
}
def dateToIso8601(date) {
def format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
def result = format.format(date)
return result[0..21] + ':' + result[22..-1]
}
def sha1(file) {
MessageDigest md = MessageDigest.getInstance('SHA-1')
file.eachByte 4096, {bytes, size ->
md.update(bytes, 0, size)
}
return md.digest().collect {String.format "%02x", it}.join()
}
def artifactTree(project, artifact) {
if (!project.ext.has('tree_resolver'))
project.ext.tree_resolver = 1
def cfg = project.configurations.create('tree_resolver_' + project.ext.tree_resolver++)
def dep = project.dependencies.create(artifact)
cfg.dependencies.add(dep)
def files = cfg.resolve()
return getArtifacts(project, cfg)
}
def getArtifacts(project, config) {
def ret = [:]
config.resolvedConfiguration.resolvedArtifacts.each {
def art = [
group: it.moduleVersion.id.group,
name: it.moduleVersion.id.name,
version: it.moduleVersion.id.version,
classifier: it.classifier,
extension: it.extension,
file: it.file
]
def key = art.group + ':' + art.name
def folder = "${art.group.replace('.', '/')}/${art.name}/${art.version}/"
def filename = "${art.name}-${art.version}"
if (art.classifier != null)
filename += "-${art.classifier}"
filename += ".${art.extension}"
def path = "${folder}${filename}"
def url = "https://libraries.minecraft.net/${path}"
if (!checkExists(url)) {
url = "https://files.minecraftforge.net/maven/${path}"
/*
project.logger.lifecycle("Artifact: ${path}")
def repo = project.file("build/dep_repo/${folder}")
repo.mkdirs()
copy {
from art.file
into folder
rename { filename }
}
project.file("build/dep_repo/${path}.sha1").text = sha1(it.file)
*/
}
ret[key] = [
name: "${art.group}:${art.name}:${art.version}" + (art.classifier == null ? '' : ":${art.classifier}") + (art.extension == 'jar' ? '' : "@${art.extension}"),
downloads: [
artifact: [
path: path,
url: url,
sha1: sha1(art.file),
size: art.file.length()
]
]
]
}
return ret
}
def checkExists(url) {
def code = new URL(url).openConnection().with {
requestMethod = 'HEAD'
connect()
responseCode
}
return code == 200
}
def getClasspath(project, libs, artifact) {
def ret = []
artifactTree(project, artifact).each { key, lib ->
libs[lib.name] = lib
if (lib.name != artifact)
ret.add(lib.name)
}
return ret
}
//evaluationDependsOnChildren()
task setup() {
dependsOn ':clean:extractMapped'
dependsOn ':forge:extractMapped' //These must be strings so that we can do lazy resolution. Else we need evaluationDependsOnChildren above
}