Files
MinecraftForge/build.gradle
T

1321 lines
53 KiB
Groovy

import de.undercouch.gradle.tasks.download.Download
import groovy.json.JsonBuilder
import net.minecraftforge.forge.tasks.checks.CheckATs
import net.minecraftforge.forge.tasks.checks.CheckExcs
import net.minecraftforge.forge.tasks.checks.CheckPatches
import net.minecraftforge.forge.tasks.checks.CheckSAS
import net.minecraftforge.forge.tasks.checks.CheckTask
import java.nio.file.Files
import java.util.Date
import java.util.LinkedHashMap
import net.minecraftforge.forge.tasks.*
import static net.minecraftforge.forge.tasks.Util.*
import net.minecraftforge.gradle.common.tasks.ApplyBinPatches
import net.minecraftforge.gradle.common.tasks.CheckJarCompatibility
import net.minecraftforge.gradle.common.tasks.DownloadMavenArtifact
import net.minecraftforge.gradle.common.tasks.ExtractInheritance
import net.minecraftforge.gradle.common.tasks.SignJar
import net.minecraftforge.gradle.patcher.tasks.GeneratePatches
import net.minecraftforge.gradle.userdev.tasks.RenameJar
import net.minecraftforge.gradleutils.PomUtils
import org.apache.tools.ant.filters.ReplaceTokens
import org.gradle.plugins.ide.eclipse.model.SourceFolder
import org.objectweb.asm.Opcodes
plugins {
id 'org.cadixdev.licenser' version '0.6.1'
id 'com.github.ben-manes.versions' version '0.46.0'
id 'net.minecraftforge.gradleutils' version '[2.2,2.3)'
id 'eclipse'
id 'de.undercouch.download' version '5.4.0'
id 'net.minecraftforge.gradle.patcher' version '[6.0.16,6.2)' apply false
id 'net.minecraftforge.gradle.mcp' version '[6.0.16,6.2)' apply false
}
Util.init() //Init all our extension methods!
ext {
JAR_SIGNER = null
if (project.hasProperty('keystore')) {
JAR_SIGNER = [
storepass: project.properties.keystoreStorePass,
keypass: project.properties.keystoreKeyPass,
keystore: project.properties.keystore
]
}
MAPPING_CHANNEL = 'official'
MC_VERSION = '1.20.2'
MAPPING_VERSION = MC_VERSION
MC_NEXT_VERSION = '1.21'
MCP_VERSION = '20230921.100330'
SNAPSHOT = false
INSTALLER_VERSION = '2.1.+'
GIT_INFO = gradleutils.gitInfo
VERSION = gradleutils.getFilteredMCTagOffsetBranchVersion(true, '[0-9]', MC_VERSION)
// FML_VERSION = gradleutils.getFilteredMCTagOffsetBranchVersion(true, 'FML', MC_VERSION)
FORGE_VERSION = VERSION.substring(MC_VERSION.length() + 1)
BINPATCH_TOOL = 'net.minecraftforge:binarypatcher:1.1.1:fatjar'
INSTALLER_TOOLS = 'net.minecraftforge:installertools:1.3.0'
JAR_SPLITTER = 'net.minecraftforge:jarsplitter:1.1.4'
FART = 'net.minecraftforge:ForgeAutoRenamingTool:1.0.5:all'
MIN_TAG_FOR_CHANGELOG = '47.999'
}
println('Version: ' + VERSION +
' Java: ' + System.getProperty('java.version') +
' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ')' +
' Arch: ' + System.getProperty('os.arch'))
changelog {
fromTag MIN_TAG_FOR_CHANGELOG
}
def extraTxts = [
rootProject.file('CREDITS.txt'),
rootProject.file('LICENSE.txt'),
rootProject.tasks.createChangelog.outputFile
]
tasks.register('downloadVersionManifest', Download) {
src 'https://piston-meta.mojang.com/mc/game/version_manifest_v2.json'
dest file('build/versions/version_manifest.json')
useETag 'all'
onlyIfModified true
quiet true
}
tasks.register('downloadJson', Download) {
dependsOn downloadVersionManifest
inputs.file downloadVersionManifest.dest
src { downloadVersionManifest.dest.json.versions.find{ it.id == MC_VERSION }.url }
dest file("build/versions/${MC_VERSION}/version.json")
useETag 'all'
onlyIfModified true
quiet true
}
tasks.register('downloadClientRaw', Download) {
dependsOn downloadJson
inputs.file downloadJson.dest
src { downloadJson.dest.json.downloads.client.url }
dest file("build/versions/${MC_VERSION}/client.jar")
useETag 'all'
onlyIfModified true
quiet true
}
tasks.register('downloadServerRaw', Download) {
dependsOn downloadJson
inputs.file downloadJson.dest
src { downloadJson.dest.json.downloads.server.url }
dest file("build/versions/${MC_VERSION}/server.jar")
useETag 'all'
onlyIfModified true
quiet true
}
subprojects {
apply plugin: 'maven-publish'
apply plugin: 'eclipse'
apply plugin: 'java'
group = 'net.minecraftforge'
version = VERSION
//println(name + ' Version: ' + version)
repositories {
mavenCentral()
maven gradleutils.forgeMaven
maven gradleutils.minecraftLibsMaven
}
java.toolchain.languageVersion = JavaLanguageVersion.of(17)
tasks.withType(Javadoc).configureEach {
options.tags = [
'apiNote:a:<em>API Note:</em>',
'implSpec:a:<em>Implementation Requirements:</em>',
'implNote:a:<em>Implementation Note:</em>'
]
options.addStringOption('Xdoclint:all,-missing', '-public')
}
publishing {
publications {
mavenJava(MavenPublication) {
// Normal Maven/old gradle doesn't support '2.+' version wildcards
// For now we just suppress. We *should* force the resolution to pinned versions.
suppressPomMetadataWarningsFor('apiElements')
suppressPomMetadataWarningsFor('runtimeElements')
pom {
name = project.name
description = 'Modifactions to Minecraft to enable mod developers.'
url = 'https://github.com/MinecraftForge/MinecraftForge'
PomUtils.setGitHubDetails(pom, 'MinecraftForge')
license PomUtils.Licenses.LGPLv2_1
}
}
}
repositories {
maven gradleutils.publishingForgeMaven
}
}
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
options.warnings = false // Shutup deprecated for removal warnings
}
}
project(':mcp') {
apply plugin: 'net.minecraftforge.gradle.mcp'
tasks.withType(AbstractPublishToMaven.class).forEach{tsk -> tsk.enabled = false } // We don't want to publish anything
mcp {
config MC_VERSION + '-' + MCP_VERSION
pipeline = 'joined'
}
}
def sharedFmlonlyForge = { Project prj ->
prj.afterEvaluate {
[prj.tasks.universalJar, prj.tasks.installerJar].each { t ->
def signTask = prj.task([type: SignJar, dependsOn: t], "sign${t.name.capitalize()}") {
onlyIf {
JAR_SIGNER != null && t.state.failure == null
}
def jarsigner = JAR_SIGNER == null ? [:] : JAR_SIGNER
alias = 'forge'
storePass = jarsigner.storepass
keyPass = jarsigner.keypass
keyStore = jarsigner.keystore
inputFile = t.archiveFile.get().asFile
outputFile = t.archiveFile.get().asFile
}
t.finalizedBy(signTask)
}
}
prj.tasks.userdevConfig {
getArtifacts(prj, prj.configurations.installer, true).each { key, lib -> libraries.add(lib.name) }
getArtifacts(prj, prj.configurations.moduleonly, true).each { key, lib ->
libraries.add(lib.name)
modules.add(lib.name)
}
for (child in prj.ext.PACKED_DEPS) {
libraries.add(Util.getMavenDep(rootProject.tasks.findByPath(child)))
}
//libraries.add("${project.group}:${project.name}:${project.version}:launcher")
inject = '' // We don't have a userdev sourceset anymore. Empty as a gradle workaround...
runs {
client {
environment 'MCP_MAPPINGS', '{mcp_mappings}'
property 'forge.enableGameTest', 'true'
args '--launchTarget', "forge_userdev_client"
args '--version', 'MOD_DEV'
args '--assetIndex', '{asset_index}'
args '--assetsDir', '{assets_root}'
}
server {
environment 'MCP_MAPPINGS', '{mcp_mappings}'
property 'forge.enableGameTest', 'true'
args '--launchTarget', "forge_userdev_server"
}
gameTestServer {
environment 'MCP_MAPPINGS', '{mcp_mappings}'
args '--launchTarget', "forge_userdev_server_gametest"
}
data {
environment 'MCP_MAPPINGS', '{mcp_mappings}'
args '--launchTarget', "forge_userdev_data"
args '--assetIndex', '{asset_index}'
args '--assetsDir', '{assets_root}'
}
}
}
def userdevRuns = prj.tasks.userdevConfig.runs
def ignoreList = ( //bsl uses filename.startsWith, so we have to use the project name, i add '-' for saftey's sake and not wanting to ignore things that modders add. But the whole system is really dumb/fragile.
prj.configurations.moduleonly.allDependencies.collect{ it.name }
+ ['client-extra', 'fmlcore', 'javafmllanguage', 'lowcodelanguage', 'mclanguage', prj.name]
).collect{ it + '-' }.sort().join(',')
for (def run : prj.patcher.runs + userdevRuns) {
if (run.parents) continue // We already added this to the parent run config
//run.property 'bsl.debug', 'true'
run.main 'net.minecraftforge.bootstrap.BootstrapLauncher'
run.args '--gameDir', '.'
run.args '--fml.forgeVersion', FORGE_VERSION
run.args '--fml.mcVersion', MC_VERSION
run.args '--fml.forgeGroup', prj.group
run.args '--fml.mcpVersion', MCP_VERSION
run.jvmArgs '-Djava.net.preferIPv6Addresses=system'
run.client run.name.contains('client')
// SecureJarHandler bootstrap values.
run.property 'ignoreList', ignoreList
// FIXME: Without this jna doesn't work at runtime. Someone figure out why please?
run.property 'mergeModules', 'jna-5.10.0.jar,jna-platform-5.10.0.jar'
if (userdevRuns.contains(run)) {
run.property 'legacyClassPath.file', '{minecraft_classpath_file}'
run.jvmArgs '-p', '{modules}'
} else {
run.property 'legacyClassPath.file', '{runtime_classpath_file}'
run.jvmArgs '-p', prj.configurations.moduleonly.files.collect { it.path }.join(File.pathSeparator)
}
run.jvmArgs '--add-modules', 'ALL-MODULE-PATH'
// Additions to these JVM module args should be mirrored to server_files/args.txt and other similar blocks in the buildscript
run.jvmArgs '--add-exports', 'jdk.naming.dns/com.sun.jndi.dns=java.naming'
}
for (def run : prj.patcher.runs) {
def isTest = run.name.endsWith('_test')
run.taskName = run.name
run.environment 'FORGE_SPEC', prj.SPEC_VERSION
run.workingDirectory prj.file('run/' + run.name)
run.ideaModule rootProject.name + '.' + prj.name + '.' + (isTest ? 'test' : 'main')
run.mods {
minecraft { source prj.sourceSets.main }
}
if (isTest) {
run.property 'forge.enableGameTest', 'true'
run.mods {
tests { sources prj.sourceSets.test }
}
}
}
def MODULE_PATH = Util.getArtifacts(prj, prj.configurations.moduleonly, false).values().collect{"libraries/${it.downloads.artifact.path}"}.sort()
def tokens = [
TASK: 'forge_server',
MAVEN_PATH: prj.ext.MAVEN_PATH.toString(),
FORGE_VERSION: FORGE_VERSION,
MC_VERSION: MC_VERSION,
MCP_VERSION: MCP_VERSION,
FORGE_GROUP: prj.group,
IGNORE_LIST: Util.getArtifacts(prj, prj.configurations.moduleonly, false).values().collect{it.downloads.artifact.path.rsplit('/', 1)[1]}.sort().join(','),
MODULES: 'ALL-MODULE-PATH'
]
prj.task([dependsOn: rootProject.downloadServerRaw], 'makeClasspathFiles') {
doLast {
def CLASS_PATH = Util.getArtifacts(prj, prj.configurations.installer, false).values().collect{"libraries/${it.downloads.artifact.path}"} +
[
'libraries/' + Util.getMavenPath(rootProject.tasks.findByPath(':fmlloader:jar')),
"libraries/net/minecraft/server/${MC_VERSION}-${MCP_VERSION}/server-${MC_VERSION}-${MCP_VERSION}-extra.jar"
]
def claimed = CLASS_PATH.collect{ it.rsplit('/', 2)[0] }.toSet() // Allow us to override versions
try (def zip = new java.util.zip.ZipFile(rootProject.downloadServerRaw.dest)) {
CLASS_PATH += zip.getInputStream(zip.getEntry('META-INF/classpath-joined')).text.split(';')
.findAll{ it.startsWith('libraries/') && !claimed.contains(it.rsplit('/', 2)[0]) }
}
configure(prj.installerJar) {
from(rootProject.file('server_files/args.txt')) {
filter(ReplaceTokens, tokens: tokens + [MODULE_PATH: MODULE_PATH.join(';'), CLASS_PATH: CLASS_PATH.join(';')])
rename { 'data/win_args.txt' }
}
from(rootProject.file('server_files/args.txt')) {
filter(ReplaceTokens, tokens: tokens + [MODULE_PATH: MODULE_PATH.join(':'), CLASS_PATH: CLASS_PATH.join(':')])
rename { 'data/unix_args.txt' }
}
}
}
}
prj.afterEvaluate {
prj.installerJar {
dependsOn('makeClasspathFiles')
from(rootProject.file('server_files/')) {
exclude 'args.txt'
filter(ReplaceTokens, tokens: tokens)
into('data/')
}
}
}
}
project(':forge') {
evaluationDependsOn(':mcp')
apply plugin: 'java-library'
apply plugin: 'net.minecraftforge.gradle.patcher'
apply plugin: 'org.cadixdev.licenser'
applyPatches {
level 'WARNING'
}
sourceSets {
main {
java {
srcDirs = [
"$rootDir/src/main/java",
"$rootDir/src/fmlcommon/java"
]
}
resources {
srcDirs = [
"$rootDir/src/main/resources",
"$rootDir/src/generated/resources",
"$rootDir/src/fmlcommon/resources"
]
}
}
test {
java {
srcDirs = [
"$rootDir/src/test/java"
]
}
resources {
srcDirs = [
"$rootDir/src/test/resources",
"$rootDir/src/generated_test/resources"
]
}
}
}
eclipse {
classpath.file.whenMerged {
// Disable optional warnings on the minecraft decompiled source code. It just muddies the warning window and hides warnings in our own codebase
def src = entries.find { it.path == 'src/main/java' }
src.entryAttributes['ignore_optional_problems'] = 'true'
}
project.resourceFilter {
appliesTo = 'FOLDERS'
type = 'EXCLUDE_ALL'
matcher {
id = 'org.eclipse.ui.ide.multiFilter'
arguments = '1.0-name-matches-false-false-run'
}
}
}
ext {
SPEC_VERSION = gradleutils.gitInfo.tag
// The new versioning sceme is <MCVersion>-<ForgeMC>.<RB>.<CommitsSinceRB>
// ForgeMC is a unique identifier for every MC version we have supported.
// Essentially, the same as the old, except dropping the first number, and the builds are no longer unique.
MCP_ARTIFACT = project(':mcp').mcp.config.get()
VERSION_JSON = project(':mcp').file('build/mcp/downloadJson/version.json')
PACKED_DEPS = [':fmlcore:jar', ':fmlloader:jar', ':fmlearlydisplay:jar', ':javafmllanguage:jar', ':lowcodelanguage:jar', ':mclanguage:jar']
MAVEN_PATH = "${group.replace('.', '/')}/${project.name}/${VERSION}"
}
configurations {
// Don't pull all libraries, if we're missing something, add it to the installer list so the installer knows to download it.
installer { transitive = false }
moduleonly { transitive = false }
api.extendsFrom(installer)
}
dependencies {
moduleonly(libs.bootstrap)
moduleonly(libs.securemodules) // Needed by bootstrap
moduleonly(libs.unsafe) // Needed by securemodules
moduleonly(libs.bundles.asm) // Needed by all the black magic
moduleonly(libs.jarjar.fs) // Filesystems need to be on the bootstrap? I think thats why this is here.
moduleonly(libs.bundles.jimfs) // In memory file system used for ForgeDev launches
installer(libs.unsafe)
installer(libs.securemodules)
installer(libs.bundles.asm) // Needed by all the black magic
installer(libs.accesstransformers)
installer(libs.antlr.runtime) // Dep of AccessTransformer
installer(libs.eventbus)
installer(libs.typetools) // Dep of EventBus
installer(libs.forgespi)
installer(libs.coremods)
installer(libs.nashorn) // Dep of Coremods
installer(libs.modlauncher)
installer(libs.mergetool.api)
installer(libs.bundles.night.config)
installer(libs.maven.artifact)
installer(libs.bundles.terminalconsoleappender)
installer(libs.mixin)
installer(libs.bundles.jarjar)
implementation project(':fmlcore')
implementation project(':fmlloader')
implementation project(':fmlearlydisplay')
implementation project(':javafmllanguage')
implementation project(':lowcodelanguage')
implementation project(':mclanguage')
runtimeOnly(libs.bootstrap)
}
patcher {
excs.from file("$rootDir/src/main/resources/forge.exc")
parent = project(':mcp')
mcVersion = MC_VERSION
mappings channel: MAPPING_CHANNEL, version: MAPPING_VERSION
patches = file("$rootDir/patches/minecraft")
patchedSrc = file('src/main/java')
srgPatches = false
accessTransformers.from file("$rootDir/src/main/resources/META-INF/accesstransformer.cfg")
sideAnnotationStrippers.from file("$rootDir/src/main/resources/forge.sas")
runs {
forge_client {
property 'eventbus.checkTypesOnDispatch', 'true'
property 'org.lwjgl.system.SharedLibraryExtractDirectory', 'lwjgl_dll'
args '--launchTarget', 'forge_dev_client',
'--username', 'Dev',
'--version', project.name,
'--accessToken', '0',
'--userType', 'mojang',
'--versionType', 'release',
'--assetsDir', downloadAssets.output,
'--assetIndex', "{asset_index}"
}
forge_client_test {
parent runs.forge_client
}
forge_server {
args '--launchTarget', 'forge_dev_server'
}
forge_server_test {
parent runs.forge_server
}
forge_server_gametest {
args '--launchTarget', 'forge_dev_server_gametest'
}
forge_server_gametest_test {
parent runs.forge_server_gametest
}
forge_data {
args '--launchTarget', 'forge_dev_data',
'--mod', 'forge',
'--all',
'--validate',
'--output', rootProject.file('src/generated/resources/'),
'--validate',
'--existing', sourceSets.main.resources.srcDirs[0],
'--assetsDir', downloadAssets.output,
'--assetIndex', "{asset_index}"
}
forge_data_test {
args '--launchTarget', 'forge_dev_data',
'--mod', '.+',
'--all',
'--validate',
'--output', rootProject.file('src/generated_test/resources/'),
'--existing', sourceSets.main.resources.srcDirs[0],
'--existing', sourceSets.test.resources.srcDirs[0],
'--assetsDir', downloadAssets.output,
'--assetIndex', "{asset_index}"
}
}
}
afterEvaluate {
if (!patcher.srgPatches) {
srg2mcpClean {
dependsOn = []
input = project(':mcp').setupMCP.output
}
userdevJar {
onlyIf = { t -> true }
}
def patches = project.file('build/genPatchesForUserdev/output/')
patches.mkdirs()
def genPatchesForUserdev = tasks.register('genPatchesForUserdev', GeneratePatches){
base = project(':mcp').setupMCP.output
modified = applyRangeMapBase.output
originalPrefix = genPatches.originalPrefix
modifiedPrefix = genPatches.modifiedPrefix
output = patches
autoHeader true
lineEnding = '\n'
}
bakePatches {
dependsOn = []
input = genPatchesForUserdev.get().output
}
}
}
ext {
MANIFESTS = [
'/': [
'GitCommit': gradleutils.gitInfo.abbreviatedId,
'Git-Branch': gradleutils.gitInfo.branch,
'FML-System-Mods': 'forge'
] as LinkedHashMap,
'net/minecraftforge/versions/forge/': [
'Specification-Title': 'Forge',
'Specification-Vendor': 'Forge Development LLC',
'Specification-Version': SPEC_VERSION,
'Implementation-Title': project.group,
'Implementation-Version': project.version.substring(MC_VERSION.length() + 1),
'Implementation-Vendor': 'Forge Development LLC'
] as LinkedHashMap,
'net/minecraftforge/versions/mcp/': [
'Specification-Title': 'Minecraft',
'Specification-Vendor': 'Mojang',
'Specification-Version': MC_VERSION,
'Implementation-Title': 'MCP',
'Implementation-Version': MCP_VERSION,
'Implementation-Vendor': 'Forge'
] as LinkedHashMap,
'net/minecraftforge/fml/javafmlmod/': [
'Specification-Title': 'Mod Language Provider',
'Specification-Vendor': 'Forge Development LLC',
'Specification-Version': '1',
'Implementation-Title': 'FML Java Mod',
'Implementation-Version': SPEC_VERSION,
'Implementation-Vendor': 'Forge'
] as LinkedHashMap,
'net/minecraftforge/fml/mclanguageprovider/': [
'Specification-Title': 'Mod Language Provider',
'Specification-Vendor': 'Forge Development LLC',
'Specification-Version': '1',
'Implementation-Title': 'Minecraft Language Mod Provider',
'Implementation-Version': '1',
'Implementation-Vendor': 'Forge'
] as LinkedHashMap,
'net/minecraftforge/fml/loading/': [
'Specification-Title': 'Launcher',
'Specification-Vendor': 'Forge Development LLC',
'Specification-Version': '1',
'Implementation-Title': 'FML Launcher',
'Implementation-Version': SPEC_VERSION,
'Implementation-Vendor': 'Forge'
] as LinkedHashMap
]
}
tasks.register('downloadCrowdin', Download) {
src 'https://files.minecraftforge.net/crowdin.zip'
dest file('build/crowdin.zip')
useETag 'all'
onlyIfModified true
quiet true
}
sharedFmlonlyForge.call(project)
task downloadLibraries(type: DownloadLibraries, dependsOn: ':mcp:setupMCP') {
input = VERSION_JSON
output = rootProject.file('build/libraries/')
}
task extractInheritance(type: ExtractInheritance, dependsOn: [downloadLibraries]) {
tool = INSTALLER_TOOLS + ':fatjar'
args.add '--annotations'
input = genJoinedBinPatches.cleanJar
libraries.addAll downloadLibraries.librariesOutput.map { rf -> Files.readAllLines(rf.asFile.toPath()).stream().map(File::new).collect(java.util.stream.Collectors.toList()) }
}
tasks.register("findFieldInstanceChecks", FieldCompareFinder) {
jar = createJoinedSRG.output
output = rootProject.file('src/main/resources/coremods/field_to_instanceof.json')
fields {
/* 1.17 changed most things to use Tags. So this isn't nessasary anymore so just make an empty list
bows {
cls = 'net/minecraft/world/item/Items'
name = 'f_42411_'
replacement = 'net/minecraft/world/item/BowItem'
}
crossbows {
cls = 'net/minecraft/world/item/Items'
name = 'f_42717_'
replacement = 'net/minecraft/world/item/CrossbowItem'
}
*/
}
}
tasks.register("findFinalizeSpawnTargets", BytecodePredicateFinder) {
jar = createJoinedSRG.output
output = rootProject.file('src/main/resources/coremods/finalize_spawn_targets.json')
predicate = {
parent, node, insn ->
'net/minecraft/world/level/BaseSpawner' != parent.name // Ignore this class as we special case it.
&& insn.getOpcode() == Opcodes.INVOKEVIRTUAL
&& insn.name.equals('m_6518_')
&& insn.desc.equals('(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/MobSpawnType;Lnet/minecraft/world/entity/SpawnGroupData;Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/world/entity/SpawnGroupData;')
}
}
tasks.register('validateDeprecations', ValidateDeprecations) {
input = tasks.jar.archiveFile
mcVersion = MC_VERSION
}
tasks.jar.finalizedBy 'validateDeprecations'
tasks.register("downloadInstaller", DownloadMavenArtifact) {
artifact = "net.minecraftforge:installer:${INSTALLER_VERSION}:shrunk"
changing = true
}
tasks.register("downloadClientSlim", DownloadMavenArtifact) {
artifact = "net.minecraft:client:${MC_VERSION}-${MCP_VERSION}:slim"
}
tasks.register("downloadClientExtra", DownloadMavenArtifact) {
artifact = "net.minecraft:client:${MC_VERSION}-${MCP_VERSION}:extra"
}
tasks.register("downloadServerSlim", DownloadMavenArtifact) {
artifact = "net.minecraft:server:${MC_VERSION}-${MCP_VERSION}:slim"
}
tasks.register("downloadServerExtra", DownloadMavenArtifact) {
artifact = "net.minecraft:server:${MC_VERSION}-${MCP_VERSION}:extra"
}
tasks.register("downloadJoinedSlim", DownloadMavenArtifact) {
artifact = "net.minecraft:joined:${MC_VERSION}-${MCP_VERSION}:slim"
}
tasks.register("downloadJoinedExtra", DownloadMavenArtifact) {
artifact = "net.minecraft:joined:${MC_VERSION}-${MCP_VERSION}:extra"
}
tasks.register("createJoinedSRG", DownloadMavenArtifact) {
artifact = "net.minecraft:joined:${MC_VERSION}-${MCP_VERSION}:srg"
}
tasks.register("createClientSRG", RenameJar) {
tool = FART
args = ['--input', '{input}', '--output', '{output}', '--names', '{mappings}', '--ann-fix', '--ids-fix', '--src-fix', '--record-fix']
mappings = createMcp2Srg.srg
input = downloadClientSlim.output
output = file("build/createClientSRG/output.jar")
}
tasks.register("createServerSRG", RenameJar) {
tool = FART
args = ['--input', '{input}', '--output', '{output}', '--names', '{mappings}', '--ann-fix', '--ids-fix', '--src-fix', '--record-fix']
mappings = createMcp2Srg.srg
input = downloadServerSlim.output
output = file("build/createServerSRG/output.jar")
}
genClientBinPatches {
tool = BINPATCH_TOOL
cleanJar = createClientSRG.output
}
genServerBinPatches {
tool = BINPATCH_TOOL
cleanJar = createServerSRG.output
}
genJoinedBinPatches {
tool = BINPATCH_TOOL
cleanJar = createJoinedSRG.output
}
tasks.register("applyClientBinPatches", ApplyBinPatches) {
tool = BINPATCH_TOOL
clean = genClientBinPatches.cleanJar
patch = genClientBinPatches.output
}
tasks.register("applyServerBinPatches", ApplyBinPatches) {
tool = BINPATCH_TOOL
clean = genServerBinPatches.cleanJar
patch = genServerBinPatches.output
}
tasks.register("applyJoinedBinPatches", ApplyBinPatches) {
tool = BINPATCH_TOOL
clean = genJoinedBinPatches.cleanJar
patch = genJoinedBinPatches.output
}
tasks.register('checkAll') {
dependsOn 'checkLicenses'
group = 'checks'
}
tasks.register('checkAllAndFix') {
dependsOn 'findFinalizeSpawnTargets', 'findFieldInstanceChecks', 'checkLicenses'
group = 'checks'
}
CheckTask.registerTask(tasks, 'ATs', CheckATs) {
dependsOn extractInheritance, createSrg2Mcp
ats.from patcher.accessTransformers
inheritance = extractInheritance.output
mappings = createSrg2Mcp.output
}
CheckTask.registerTask(tasks, 'SAS', CheckSAS) {
dependsOn extractInheritance
sass.from patcher.sideAnnotationStrippers
inheritance = extractInheritance.output
}
CheckTask.registerTask(tasks, 'Excs', CheckExcs) {
dependsOn jar
binary = jar.archiveFile.get().asFile
excs.from patcher.excs
}
CheckTask.registerTask(tasks, 'Patches', CheckPatches) {
dependsOn genPatches
patchDir = file("$rootDir/patches")
patchesWithS2SArtifact = [
'minecraft/net/minecraft/client/renderer/ViewArea.java.patch',
'minecraft/net/minecraft/data/models/blockstates/Variant.java.patch',
]
}
genPatches {
finalizedBy checkAndFixPatches
autoHeader true
lineEnding = '\n'
}
def baseForgeVersionProperty = project.objects.property(String)
baseForgeVersionProperty.set(project.provider { TeamcityRequests.attemptFindBase(rootDir) ?: getLatestForgeVersion(MC_VERSION) })
baseForgeVersionProperty.finalizeValueOnRead()
def jarCompatibilityTaskSetup = { task ->
task.group = 'jar compatibility'
task.onlyIf {
baseForgeVersionProperty.getOrNull() != null
}
}
tasks.register('setupCheckJarCompatibility', SetupCheckJarCompatibility) {
inputVersion = baseForgeVersionProperty
}
tasks.register('applyBaseCompatibilityJarBinPatches', ApplyBinPatches) {
jarCompatibilityTaskSetup(it)
clean = project.tasks.createJoinedSRG.output
patch = project.tasks.named('setupCheckJarCompatibility').flatMap { it.baseBinPatchesOutput }
output = project.layout.buildDirectory.dir(name).map { it.file('output.jar') }
}
tasks.register('mergeBaseForgeJar', MergeJars) {
jarCompatibilityTaskSetup(it)
inputJars.from(project.tasks.named('applyBaseCompatibilityJarBinPatches').flatMap { it.output })
inputJars.from(baseForgeVersionProperty.map { inputVersion ->
def output = project.layout.buildDirectory.dir(name).map { it.file("forge-${inputVersion}-universal.jar") }.get().asFile
project.rootProject.extensions.download.run {
src "https://maven.minecraftforge.net/net/minecraftforge/forge/${inputVersion}/forge-${inputVersion}-universal.jar"
dest output
}
return output
})
}
tasks.register('checkJarCompatibility', CheckJarCompatibility) {
jarCompatibilityTaskSetup(it)
dependsOn 'setupCheckJarCompatibility'
baseJar = project.tasks.named('mergeBaseForgeJar').flatMap { it.output }
baseLibraries.from(project.tasks.named('createJoinedSRG').flatMap { it.output })
inputJar = project.tasks.named('reobfJar').flatMap { it.output }
concreteLibraries.from(project.PACKED_DEPS.collect { project.rootProject.tasks.getByPath(it).archiveFile })
commonLibraries.from(project.configurations.minecraftImplementation)
commonLibraries.from(project.configurations.installer)
commonLibraries.from(project.configurations.moduleonly)
}
task launcherJson(type: LauncherJson) {
packedDependencies = [':fmlloader:jar',':fmlearlydisplay:jar']
doFirst {
def forge_client = project(':forge').patcher.runs.forge_client
json = [
_comment_: comment,
id: id,
time: timestamp,
releaseTime: timestamp,
type: 'release',
mainClass: 'net.minecraftforge.bootstrap.BootstrapLauncher',
inheritsFrom: MC_VERSION,
logging: {},
arguments: [
game: ['--launchTarget', 'forge_client',
'--fml.forgeVersion', FORGE_VERSION,
'--fml.mcVersion', MC_VERSION,
'--fml.forgeGroup', project.group,
'--fml.mcpVersion', MCP_VERSION],
jvm: ['-Djava.net.preferIPv6Addresses=system',
"-DignoreList=${forge_client.properties.ignoreList},\${version_name}.jar",
"-DmergeModules=${forge_client.properties.mergeModules}",
'-DlibraryDirectory=${library_directory}',
'-p', Util.getArtifacts(project, configurations.moduleonly, false).values().collect{'${library_directory}/' + it.downloads.artifact.path}.join('${classpath_separator}'),
'--add-modules', 'ALL-MODULE-PATH',
// Additions to these JVM module args should be mirrored to server_files/args.txt and other similar blocks in the buildscript
'--add-exports', 'jdk.naming.dns/com.sun.jndi.dns=java.naming'
]
],
libraries: []
]
}
}
task installerJson(type: InstallerJson, dependsOn: [launcherJson, genClientBinPatches, applyClientBinPatches, applyServerBinPatches, 'signUniversalJar']) {
ext {
// remove :fatjar
BIN_PATCHER = BINPATCH_TOOL.substring(0, BINPATCH_TOOL.length() - 1 - BINPATCH_TOOL.split(':')[3].length())
}
input.from applyClientBinPatches.output, applyServerBinPatches.output, genClientBinPatches.toolJar, launcherJson.output
icon = rootProject.file('icon.ico')
packedDependencies = PACKED_DEPS
doFirst {
def libs = libraries
def INSTALLER_TOOLS_CLASSPATH = getClasspath(project, libs, INSTALLER_TOOLS)
def JAR_SPLITTER_CLASSPATH = getClasspath(project, libs, JAR_SPLITTER)
json = [
_comment_: launcherJson.comment,
spec: 1,
profile: project.name,
version: launcherJson.id,
path: null,
minecraft: MC_VERSION,
serverJarPath: '{LIBRARY_DIR}/net/minecraft/server/{MINECRAFT_VERSION}/server-{MINECRAFT_VERSION}.jar',
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]"
],
MOJMAPS: [
client: "[net.minecraft:client:${MC_VERSION}-${MCP_VERSION}:mappings@txt]",
server: "[net.minecraft:server:${MC_VERSION}-${MCP_VERSION}:mappings@txt]"
],
MERGED_MAPPINGS: [
client: "[${MCP_ARTIFACT.group}:${MCP_ARTIFACT.name}:${MCP_ARTIFACT.version}:mappings-merged@txt]",
server: "[${MCP_ARTIFACT.group}:${MCP_ARTIFACT.name}:${MCP_ARTIFACT.version}:mappings-merged@txt]"
],
BINPATCH: [
client: '/data/client.lzma',
server: '/data/server.lzma'
],
MC_UNPACKED: [
client: "[net.minecraft:client:${MC_VERSION}-${MCP_VERSION}:unpacked]",
server: "[net.minecraft:server:${MC_VERSION}-${MCP_VERSION}:unpacked]"
],
MC_SLIM: [
client: "[net.minecraft:client:${MC_VERSION}-${MCP_VERSION}:slim]",
server: "[net.minecraft:server:${MC_VERSION}-${MCP_VERSION}:slim]"
],
MC_SLIM_SHA: [
client: "'${downloadClientSlim.output.get().asFile.sha1()}'",
server: "'${downloadServerSlim.output.get().asFile.sha1()}'"
],
MC_EXTRA: [
client: "[net.minecraft:client:${MC_VERSION}-${MCP_VERSION}:extra]",
server: "[net.minecraft:server:${MC_VERSION}-${MCP_VERSION}:extra]"
],
MC_EXTRA_SHA: [
client: "'${downloadClientExtra.output.get().asFile.sha1()}'",
server: "'${downloadServerExtra.output.get().asFile.sha1()}'"
],
MC_SRG: [
client: "[net.minecraft:client:${MC_VERSION}-${MCP_VERSION}:srg]",
server: "[net.minecraft:server:${MC_VERSION}-${MCP_VERSION}:srg]"
],
/*MC_SRG_SHA: [
client: "'${createClientSRG.output.sha1()}'",
server: "'${createServerSRG.output.sha1()}'"
],*/
PATCHED: [
client: "[${project.group}:${project.name}:${project.version}:client]",
server: "[${project.group}:${project.name}:${project.version}:server]"
],
PATCHED_SHA: [
client: "'${applyClientBinPatches.output.get().asFile.sha1()}'",
server: "'${applyServerBinPatches.output.get().asFile.sha1()}'"
],
MCP_VERSION: [
client: "'${MCP_VERSION}'",
server: "'${MCP_VERSION}'"
]
],
processors: [
[
sides: ['server'],
jar: INSTALLER_TOOLS,
classpath: INSTALLER_TOOLS_CLASSPATH,
args: [
'--task', 'EXTRACT_FILES',
'--archive', '{INSTALLER}',
'--from', 'data/run.sh',
'--to', '{ROOT}/run.sh',
'--exec', '{ROOT}/run.sh',
//'--from', "data/run_forge_${VERSION.replace('-', '_').sh",
//'--to', '{ROOT}/run_forge_${VERSION.replace('-', '_').sh',
//'--exec', '{ROOT}/run_forge_${VERSION.replace('-', '_').sh',
'--from', 'data/run.bat',
'--to', '{ROOT}/run.bat',
//'--from', 'data/run_forge_${VERSION.replace('-', '_').bat',
//'--to', '{ROOT}/run_forge_${VERSION.replace('-', '_').bat',
'--from', 'data/user_jvm_args.txt',
'--to', '{ROOT}/user_jvm_args.txt',
'--optional', '{ROOT}/user_jvm_args.txt',
'--from', 'data/win_args.txt',
'--to', "{ROOT}/libraries/${MAVEN_PATH}/win_args.txt",
'--from', 'data/unix_args.txt',
'--to', "{ROOT}/libraries/${MAVEN_PATH}/unix_args.txt"
]
], [
sides: ['server'],
jar: INSTALLER_TOOLS,
classpath: INSTALLER_TOOLS_CLASSPATH,
args: [
'--task', 'BUNDLER_EXTRACT',
'--input', '{MINECRAFT_JAR}',
'--output', '{ROOT}/libraries/',
'--libraries'
]
], [
sides: ['server'],
jar: INSTALLER_TOOLS,
classpath: INSTALLER_TOOLS_CLASSPATH,
args: [
'--task', 'BUNDLER_EXTRACT',
'--input', '{MINECRAFT_JAR}',
'--output', '{MC_UNPACKED}',
'--jar-only'
]
], [
jar: INSTALLER_TOOLS,
classpath: INSTALLER_TOOLS_CLASSPATH,
args: [
'--task', 'MCP_DATA',
'--input', "[${MCP_ARTIFACT.descriptor}]",
'--output', '{MAPPINGS}',
'--key', 'mappings'
]
], [
jar: INSTALLER_TOOLS,
classpath: INSTALLER_TOOLS_CLASSPATH,
args: [
'--task', 'DOWNLOAD_MOJMAPS',
'--version', MC_VERSION,
'--side', '{SIDE}',
'--output', '{MOJMAPS}'
]
], [
jar: INSTALLER_TOOLS,
classpath: INSTALLER_TOOLS_CLASSPATH,
args: [
'--task', 'MERGE_MAPPING',
'--left', '{MAPPINGS}',
'--right', '{MOJMAPS}',
'--output', '{MERGED_MAPPINGS}',
'--classes', '--reverse-right'
]
], [
sides: ['client'],
jar: JAR_SPLITTER,
classpath: JAR_SPLITTER_CLASSPATH,
args: [
'--input', '{MINECRAFT_JAR}',
'--slim', '{MC_SLIM}',
'--extra', '{MC_EXTRA}',
'--srg', '{MERGED_MAPPINGS}'
],
outputs: [
'{MC_SLIM}': '{MC_SLIM_SHA}',
'{MC_EXTRA}': '{MC_EXTRA_SHA}'
]
], [
sides: ['server'],
jar: JAR_SPLITTER,
classpath: JAR_SPLITTER_CLASSPATH,
args: [
'--input', '{MC_UNPACKED}',
'--slim', '{MC_SLIM}',
'--extra', '{MC_EXTRA}',
'--srg', '{MERGED_MAPPINGS}'
],
outputs: [
'{MC_SLIM}': '{MC_SLIM_SHA}',
'{MC_EXTRA}': '{MC_EXTRA_SHA}'
]
], [
jar: FART,
classpath: getClasspath(project, libs, FART),
args: [
'--input', '{MC_SLIM}',
'--output', '{MC_SRG}',
'--names', '{MERGED_MAPPINGS}',
'--ann-fix', '--ids-fix', '--src-fix', '--record-fix'
]/*,
outputs: [
'{MC_SRG}': '{MC_SRG_SHA}'
]
*/
], [
jar: BIN_PATCHER,
classpath: getClasspath(project, libs, BIN_PATCHER),
args: [
'--clean', '{MC_SRG}',
'--output', '{PATCHED}',
'--apply', '{BINPATCH}'
]/*, Because Vignette is unstable, it screws with the entry order of the binpatched jar, so we can't use the hash right now
// Re-enable this when https://github.com/CadixDev/Vignette/issues/1 is solved
outputs: [
'{PATCHED}': '{PATCHED_SHA}'
]*/
]
]
]
getClasspath(project, libs, MCP_ARTIFACT.descriptor) //Tell it to download mcp_config
}
}
universalJar {
dependsOn downloadCrowdin
from zipTree(downloadCrowdin.dest).matching {
include 'assets/forge/lang/*.json'
}
from extraTxts
duplicatesStrategy = 'exclude'
doFirst {
MANIFESTS.each{ pkg, values ->
if (pkg == '/') {
manifest.attributes(values)
} else {
manifest.attributes(values, pkg)
}
}
}
}
task installerJar(type: InstallerJar, dependsOn: [genClientBinPatches, genServerBinPatches, 'signUniversalJar', launcherJson]) {
packedDependencies = PACKED_DEPS
from(extraTxts)
from(rootProject.file('/forge_installer_logo.png')) {
rename { 'big_logo.png' }
}
from(genClientBinPatches.output) {
rename { 'data/client.lzma' }
}
from(genServerBinPatches.output) {
rename { 'data/server.lzma' }
}
}
tasks.register('devInstallerJar', DevInstallerJar) {
input = installerJar.archiveFile
}
task makeMdk(type: Zip) {
archiveBaseName = project.name
archiveClassifier = 'mdk'
archiveVersion = project.version
destinationDirectory = file('build/libs')
from rootProject.file('gradlew')
from rootProject.file('gradlew.bat')
from extraTxts
from(rootProject.file('gradle/')){
into('gradle/')
}
from(rootProject.file('mdk/')){
rootProject.file('mdk/gitignore.txt').eachLine{
if (!it.trim().isEmpty() && !it.trim().startsWith('#'))
exclude it
}
filter(ReplaceTokens, tokens: [
FORGE_VERSION: FORGE_VERSION,
FORGE_GROUP: project.group,
FORGE_NAME: project.name,
MC_VERSION: MC_VERSION,
MAPPING_CHANNEL: MAPPING_CHANNEL,
MAPPING_VERSION: MAPPING_VERSION,
FORGE_SPEC_VERSION: SPEC_VERSION.split("\\.")[0],
MC_NEXT_VERSION: MC_NEXT_VERSION
])
rename 'gitignore\\.txt', '.gitignore'
rename 'gitattributes\\.txt', '.gitattributes'
}
from(rootProject.file('src/generated_test/resources/mdk_datagen/')) {
into('src/main/resources/')
exclude '**/.cache/'
}
}
license {
header = file("$rootDir/LICENSE-header.txt")
include 'net/minecraftforge/'
exclude 'net/minecraftforge/common/LenientUnboundedMapCodec.java'
tasks {
main {
files.from files("$rootDir/src/main/java")
}
test {
files.from files("$rootDir/src/test/java")
}
}
}
tasks.register('genAllData') {
dependsOn 'forge_data', 'forge_mdk_data', 'forge_test_data'
}
tasks.eclipse.dependsOn('genEclipseRuns')
if (project.hasProperty('UPDATE_MAPPINGS')) {
extractRangeMap {
sources.from sourceSets.test.java.srcDirs
addDependencies compileTestJava.classpath
}
applyRangeMap {
sources.from sourceSets.test.java.srcDirs
}
sourceSets.test.java.srcDirs.each { extractMappedNew.addTarget it }
}
tasks.named('javadoc', Javadoc).configure {
description 'Generates the combined javadocs for the FML projects and the main Forge project'
var includedProjects = [ ':fmlcore', ':fmlloader', ':javafmllanguage', ':mclanguage' ]
source includedProjects.collect { project(it).sourceSets.main.allJava }
classpath = classpath + files(includedProjects.collect { project(it).sourceSets.main.compileClasspath })
var docsDir = rootProject.file('src/docs/')
inputs.dir(docsDir)
.withPropertyName('docs resources directory')
.withPathSensitivity(PathSensitivity.RELATIVE)
.optional()
failOnError = false
// Exclude the Minecraft classes if not enabled
if (!project.hasProperty('generateAllDocumentation')) {
exclude 'net/minecraft/**'
exclude 'com/mojang/**'
}
exclude 'mcp/**'
options.addStringOption('Xdoclint:all,-missing', '-public')
options {
stylesheetFile = new File(docsDir, 'stylesheet.css')
tags = [
'apiNote:a:<em>API Note:</em>',
'implSpec:a:<em>Implementation Requirements:</em>',
'implNote:a:<em>Implementation Note:</em>'
]
groups = [
'Forge Mod Loader': [
'net.minecraftforge.fml.common.asm*',
'net.minecraftforge.fml.loading*',
'net.minecraftforge.fml.server*'
],
'FML Core': [
'net.minecraftforge.fml',
'net.minecraftforge.fml.config*',
'net.minecraftforge.fml.event*',
'net.minecraftforge.fml.util*'
],
'FML Common': [
'net.minecraftforge.fml.core',
'net.minecraftforge.fml.event.config',
'net.minecraftforge.fml.event.lifecycle'
],
'FML Java/MC Language Providers': [
'net.minecraftforge.fml.common',
'net.minecraftforge.fml.javafmlmod',
'net.minecraftforge.fml.mclanguageprovider'
],
'Minecraft Forge API': [
'net.minecraftforge*'
]
]
author = false
noSince = true
noHelp = true
bottom = "Minecraft Forge is an open source modding API for Minecraft: Java Edition, licensed under the Lesser GNU General Public License, version 2.1."
windowTitle = "Minecraft Forge API ${VERSION}"
docTitle = "Minecraft Forge API - ${FORGE_VERSION} for Minecraft ${MC_VERSION}"
header = "<div style=\"margin-top: 9px;padding: 5px 6px;\"><strong>${FORGE_VERSION} for Minecraft ${MC_VERSION}</strong></div>"
}
doLast {
project.copy {
from docsDir
exclude '/stylesheet.css'
into destinationDir
}
}
}
publishing {
publications {
mavenJava(MavenPublication) {
artifact universalJar
artifact installerJar
artifact makeMdk
artifact userdevJar
artifact sourcesJar
}
}
}
// Since we need the modules in the bootstrap, we need to make sure they are compiled before we do each run
afterEvaluate { prepareRuns.dependsOn(PACKED_DEPS) }
// Make sure we run bin compat checking during local testing.
if (!System.env.MAVEN_USER || !System.env.MAVEN_PASSWORD)
publish.dependsOn(':forge:checkJarCompatibility')
}
tasks.register('setup') {
dependsOn ':forge:extractMapped'
if (findProject(':clean'))
dependsOn ':clean:extractMapped'
}
tasks.register('doChecks') {
dependsOn ':forge:checkJarCompatibility'
dependsOn ':forge:publish'
}
if (System.env.TEAMCITY_VERSION) {
//Only setup the CI environment if and only if the environment variables are set.
tasks.configureTeamCity {
doLast {
println "##teamcity[buildNumber '${project(':forge').version}']"
println "##teamcity[setParameter name='env.PUBLISHED_JAVA_ARTIFACT_VERSION' value='${project(':forge').version}']"
}
}
}
allprojects { prj ->
prj.tasks.eclipse.doFirst {
rootProject.fileTree('ide/eclipse/template/.settings/').matching { include '**/*.prefs' }.each { file ->
def target = project.file('.settings/' + file.name)
def temp = new CleanProperties().load(file)
def exst = new CleanProperties().load(target)
exst.put('eclipse.preferences.version', '1')
temp.forEach(exst::put)
exst.store(target)
}
}
}