mirror of
https://github.com/GTNewHorizons/AE2FluidCraft-Rework.git
synced 2026-11-12 08:17:32 +00:00
* gradle updateBuildScript * fix comments and commented-out code Code deletion, converting comments into javadocs, and refactoring code to not need comments. * remove redundant suppressions * replace C-style array declaration with Java-style * make private field final * remove unnecessary semicolon * extract a common part from an if * simplify boolean expression * simplify ternary if * remove unused imports * convert escaped characters for clarity * replace while with for * replace explicit types with diamond operators * replace anonymous type with lambda * enable modern Java syntax * migrate to enhanced switch * migrate to pattern variables for instanceof * remove empty javadoc * add Nonnull annotation to overrides of Nonnull methods * replace wailaStack with null When wailaStack is not null, the flow breaks out of the loop, so there's no need to confuse the reader with putting wailaStack both as the result and the parameter of the call - there's no recursion. * int cannot be bigger than its max value * suppress dataflow warning * remove redundant initializer The default value of int is 0. * null check is covered by instanceof * simplify some calls of addVertexWithUV * fix typos and add TODOs * make flipState more understandable
1513 lines
58 KiB
Groovy
1513 lines
58 KiB
Groovy
//version: 1685785062
|
|
/*
|
|
DO NOT CHANGE THIS FILE!
|
|
Also, you may replace this file at any time if there is an update available.
|
|
Please check https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/master/build.gradle for updates.
|
|
*/
|
|
|
|
|
|
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
|
import com.gtnewhorizons.retrofuturagradle.ObfuscationAttribute
|
|
import com.gtnewhorizons.retrofuturagradle.mcp.ReobfuscatedJar
|
|
import com.gtnewhorizons.retrofuturagradle.minecraft.RunMinecraftTask
|
|
import com.gtnewhorizons.retrofuturagradle.util.Distribution
|
|
import com.matthewprenger.cursegradle.CurseArtifact
|
|
import com.matthewprenger.cursegradle.CurseRelation
|
|
import com.modrinth.minotaur.dependencies.ModDependency
|
|
import com.modrinth.minotaur.dependencies.VersionDependency
|
|
import org.gradle.internal.logging.text.StyledTextOutput.Style
|
|
import org.gradle.internal.logging.text.StyledTextOutputFactory
|
|
import org.gradle.internal.xml.XmlTransformer
|
|
import org.jetbrains.gradle.ext.Application
|
|
import org.jetbrains.gradle.ext.Gradle
|
|
|
|
import javax.inject.Inject
|
|
import java.nio.file.Files
|
|
import java.nio.file.Paths
|
|
import java.util.concurrent.TimeUnit
|
|
|
|
buildscript {
|
|
repositories {
|
|
mavenCentral()
|
|
|
|
maven {
|
|
name 'forge'
|
|
url 'https://maven.minecraftforge.net'
|
|
}
|
|
maven {
|
|
// GTNH RetroFuturaGradle and ASM Fork
|
|
name "GTNH Maven"
|
|
url "http://jenkins.usrv.eu:8081/nexus/content/groups/public/"
|
|
allowInsecureProtocol = true
|
|
}
|
|
maven {
|
|
name 'sonatype'
|
|
url 'https://oss.sonatype.org/content/repositories/snapshots/'
|
|
}
|
|
maven {
|
|
name 'Scala CI dependencies'
|
|
url 'https://repo1.maven.org/maven2/'
|
|
}
|
|
|
|
mavenLocal()
|
|
}
|
|
}
|
|
plugins {
|
|
id 'java-library'
|
|
id "org.jetbrains.gradle.plugin.idea-ext" version "1.1.7"
|
|
id 'eclipse'
|
|
id 'scala'
|
|
id 'maven-publish'
|
|
id 'org.jetbrains.kotlin.jvm' version '1.8.0' apply false
|
|
id 'org.jetbrains.kotlin.kapt' version '1.8.0' apply false
|
|
id 'com.google.devtools.ksp' version '1.8.0-1.0.9' apply false
|
|
id 'org.ajoberstar.grgit' version '4.1.1' // 4.1.1 is the last jvm8 supporting version, unused, available for addon.gradle
|
|
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
|
|
id 'com.palantir.git-version' version '3.0.0' apply false
|
|
id 'de.undercouch.download' version '5.4.0'
|
|
id 'com.github.gmazzo.buildconfig' version '3.1.0' apply false // Unused, available for addon.gradle
|
|
id 'com.diffplug.spotless' version '6.13.0' apply false // 6.13.0 is the last jvm8 supporting version
|
|
id 'com.modrinth.minotaur' version '2.+' apply false
|
|
id 'com.matthewprenger.cursegradle' version '1.4.0' apply false
|
|
id 'com.gtnewhorizons.retrofuturagradle' version '1.3.14'
|
|
}
|
|
|
|
print("You might want to check out './gradlew :faq' if your build fails.\n")
|
|
|
|
boolean settingsupdated = verifySettingsGradle()
|
|
settingsupdated = verifyGitAttributes() || settingsupdated
|
|
if (settingsupdated)
|
|
throw new GradleException("Settings has been updated, please re-run task.")
|
|
|
|
// In submodules, .git is a file pointing to the real git dir
|
|
if (project.file('.git/HEAD').isFile() || project.file('.git').isFile()) {
|
|
apply plugin: 'com.palantir.git-version'
|
|
}
|
|
|
|
def out = services.get(StyledTextOutputFactory).create('an-output')
|
|
|
|
def projectJavaVersion = JavaLanguageVersion.of(8)
|
|
|
|
boolean disableSpotless = project.hasProperty("disableSpotless") ? project.disableSpotless.toBoolean() : false
|
|
|
|
checkPropertyExists("modName")
|
|
checkPropertyExists("modId")
|
|
checkPropertyExists("modGroup")
|
|
checkPropertyExists("autoUpdateBuildScript")
|
|
checkPropertyExists("minecraftVersion")
|
|
checkPropertyExists("forgeVersion")
|
|
checkPropertyExists("replaceGradleTokenInFile")
|
|
checkPropertyExists("gradleTokenVersion")
|
|
checkPropertyExists("apiPackage")
|
|
checkPropertyExists("accessTransformersFile")
|
|
checkPropertyExists("usesMixins")
|
|
checkPropertyExists("mixinPlugin")
|
|
checkPropertyExists("mixinsPackage")
|
|
checkPropertyExists("coreModClass")
|
|
checkPropertyExists("containsMixinsAndOrCoreModOnly")
|
|
checkPropertyExists("usesShadowedDependencies")
|
|
checkPropertyExists("developmentEnvironmentUserName")
|
|
|
|
propertyDefaultIfUnset("generateGradleTokenClass", "")
|
|
propertyDefaultIfUnset("includeWellKnownRepositories", true)
|
|
propertyDefaultIfUnset("noPublishedSources", false)
|
|
propertyDefaultIfUnset("usesMixinDebug", project.usesMixins)
|
|
propertyDefaultIfUnset("forceEnableMixins", false)
|
|
propertyDefaultIfUnset("channel", "stable")
|
|
propertyDefaultIfUnset("mappingsVersion", "12")
|
|
propertyDefaultIfUnset("modrinthProjectId", "")
|
|
propertyDefaultIfUnset("modrinthRelations", "")
|
|
propertyDefaultIfUnset("curseForgeProjectId", "")
|
|
propertyDefaultIfUnset("curseForgeRelations", "")
|
|
propertyDefaultIfUnset("minimizeShadowedDependencies", true)
|
|
propertyDefaultIfUnset("relocateShadowedDependencies", true)
|
|
// Deprecated properties (kept for backwards compat)
|
|
propertyDefaultIfUnset("gradleTokenModId", "")
|
|
propertyDefaultIfUnset("gradleTokenModName", "")
|
|
propertyDefaultIfUnset("gradleTokenGroupName", "")
|
|
|
|
propertyDefaultIfUnset("enableModernJavaSyntax", false) // On by default for new projects only
|
|
propertyDefaultIfUnset("enableGenericInjection", false) // On by default for new projects only
|
|
|
|
// this is meant to be set using the user wide property file. by default we do nothing.
|
|
propertyDefaultIfUnset("ideaOverrideBuildType", "") // Can be nothing, "gradle" or "idea"
|
|
|
|
project.extensions.add(com.diffplug.blowdryer.Blowdryer, "Blowdryer", com.diffplug.blowdryer.Blowdryer) // Make blowdryer available in "apply from:" scripts
|
|
if (!disableSpotless) {
|
|
apply plugin: 'com.diffplug.spotless'
|
|
apply from: Blowdryer.file('spotless.gradle')
|
|
}
|
|
|
|
String javaSourceDir = "src/main/java/"
|
|
String scalaSourceDir = "src/main/scala/"
|
|
String kotlinSourceDir = "src/main/kotlin/"
|
|
|
|
if (usesShadowedDependencies.toBoolean()) {
|
|
apply plugin: "com.github.johnrengelman.shadow"
|
|
}
|
|
|
|
java {
|
|
toolchain {
|
|
if (enableModernJavaSyntax.toBoolean()) {
|
|
languageVersion.set(JavaLanguageVersion.of(17))
|
|
} else {
|
|
languageVersion.set(projectJavaVersion)
|
|
}
|
|
vendor.set(JvmVendorSpec.AZUL)
|
|
}
|
|
if (!noPublishedSources) {
|
|
withSourcesJar()
|
|
}
|
|
}
|
|
|
|
tasks.withType(JavaCompile).configureEach {
|
|
options.encoding = "UTF-8"
|
|
}
|
|
|
|
tasks.withType(ScalaCompile).configureEach {
|
|
options.encoding = "UTF-8"
|
|
}
|
|
|
|
pluginManager.withPlugin('org.jetbrains.kotlin.jvm') {
|
|
// If Kotlin is enabled in the project
|
|
kotlin {
|
|
jvmToolchain(8)
|
|
}
|
|
// Kotlin hacks our source sets, so we hack Kotlin's tasks
|
|
def disabledKotlinTaskList = [
|
|
"kaptGenerateStubsMcLauncherKotlin",
|
|
"kaptGenerateStubsPatchedMcKotlin",
|
|
"kaptGenerateStubsInjectedTagsKotlin",
|
|
"compileMcLauncherKotlin",
|
|
"compilePatchedMcKotlin",
|
|
"compileInjectedTagsKotlin",
|
|
"kaptMcLauncherKotlin",
|
|
"kaptPatchedMcKotlin",
|
|
"kaptInjectedTagsKotlin",
|
|
"kspMcLauncherKotlin",
|
|
"kspPatchedMcKotlin",
|
|
"kspInjectedTagsKotlin",
|
|
]
|
|
tasks.configureEach { task ->
|
|
if (task.name in disabledKotlinTaskList) {
|
|
task.enabled = false
|
|
}
|
|
}
|
|
}
|
|
|
|
configurations {
|
|
create("runtimeOnlyNonPublishable") {
|
|
description = "Runtime only dependencies that are not published alongside the jar"
|
|
canBeConsumed = false
|
|
canBeResolved = false
|
|
}
|
|
|
|
create("devOnlyNonPublishable") {
|
|
description = "Runtime and compiletime dependencies that are not published alongside the jar (compileOnly + runtimeOnlyNonPublishable)"
|
|
canBeConsumed = false
|
|
canBeResolved = false
|
|
}
|
|
compileOnly.extendsFrom(devOnlyNonPublishable)
|
|
runtimeOnlyNonPublishable.extendsFrom(devOnlyNonPublishable)
|
|
}
|
|
|
|
if (enableModernJavaSyntax.toBoolean()) {
|
|
repositories {
|
|
mavenCentral {
|
|
mavenContent {
|
|
includeGroup("me.eigenraven.java8unsupported")
|
|
}
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:1.0.0'
|
|
// workaround for https://github.com/bsideup/jabel/issues/174
|
|
annotationProcessor 'net.java.dev.jna:jna-platform:5.13.0'
|
|
compileOnly('com.github.bsideup.jabel:jabel-javac-plugin:1.0.0') {
|
|
transitive = false // We only care about the 1 annotation class
|
|
}
|
|
// Allow using jdk.unsupported classes like sun.misc.Unsafe in the compiled code, working around JDK-8206937.
|
|
patchedMinecraft('me.eigenraven.java8unsupported:java-8-unsupported-shim:1.0.0')
|
|
}
|
|
|
|
tasks.withType(JavaCompile).configureEach {
|
|
if (it.name in ["compileMcLauncherJava", "compilePatchedMcJava"]) {
|
|
return
|
|
}
|
|
sourceCompatibility = 17 // for the IDE support
|
|
options.release.set(8)
|
|
|
|
javaCompiler.set(javaToolchains.compilerFor {
|
|
languageVersion.set(JavaLanguageVersion.of(17))
|
|
vendor.set(JvmVendorSpec.AZUL)
|
|
})
|
|
}
|
|
}
|
|
|
|
eclipse {
|
|
classpath {
|
|
downloadSources = true
|
|
downloadJavadoc = true
|
|
}
|
|
}
|
|
|
|
final String modGroupPath = modGroup.toString().replace('.' as char, '/' as char)
|
|
final String apiPackagePath = apiPackage.toString().replace('.' as char, '/' as char)
|
|
|
|
String targetPackageJava = javaSourceDir + modGroupPath
|
|
String targetPackageScala = scalaSourceDir + modGroupPath
|
|
String targetPackageKotlin = kotlinSourceDir + modGroupPath
|
|
if (!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) {
|
|
throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin)
|
|
}
|
|
|
|
if (apiPackage) {
|
|
targetPackageJava = javaSourceDir + modGroupPath + "/" + apiPackagePath
|
|
targetPackageScala = scalaSourceDir + modGroupPath + "/" + apiPackagePath
|
|
targetPackageKotlin = kotlinSourceDir + modGroupPath + "/" + apiPackagePath
|
|
if (!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) {
|
|
throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin)
|
|
}
|
|
}
|
|
|
|
if (accessTransformersFile) {
|
|
for (atFile in accessTransformersFile.split(",")) {
|
|
String targetFile = "src/main/resources/META-INF/" + atFile.trim()
|
|
if (!getFile(targetFile).exists()) {
|
|
throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile)
|
|
}
|
|
tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(targetFile)
|
|
tasks.srgifyBinpatchedJar.accessTransformerFiles.from(targetFile)
|
|
}
|
|
} else {
|
|
boolean atsFound = false
|
|
for (File at : sourceSets.getByName("main").resources.files) {
|
|
if (at.name.toLowerCase().endsWith("_at.cfg")) {
|
|
atsFound = true
|
|
tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(at)
|
|
tasks.srgifyBinpatchedJar.accessTransformerFiles.from(at)
|
|
}
|
|
}
|
|
for (File at : sourceSets.getByName("api").resources.files) {
|
|
if (at.name.toLowerCase().endsWith("_at.cfg")) {
|
|
atsFound = true
|
|
tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(at)
|
|
tasks.srgifyBinpatchedJar.accessTransformerFiles.from(at)
|
|
}
|
|
}
|
|
if (atsFound) {
|
|
logger.warn("Found and added access transformers in the resources folder, please configure gradle.properties to explicitly mention them by name")
|
|
}
|
|
}
|
|
|
|
if (usesMixins.toBoolean()) {
|
|
if (mixinsPackage.isEmpty()) {
|
|
throw new GradleException("\"usesMixins\" requires \"mixinsPackage\" to be set!")
|
|
}
|
|
final String mixinPackagePath = mixinsPackage.toString().replaceAll("\\.", "/")
|
|
final String mixinPluginPath = mixinPlugin.toString().replaceAll("\\.", "/")
|
|
|
|
targetPackageJava = javaSourceDir + modGroupPath + "/" + mixinPackagePath
|
|
targetPackageScala = scalaSourceDir + modGroupPath + "/" + mixinPackagePath
|
|
targetPackageKotlin = kotlinSourceDir + modGroupPath + "/" + mixinPackagePath
|
|
if (!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) {
|
|
throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin)
|
|
}
|
|
|
|
if (!mixinPlugin.isEmpty()) {
|
|
String targetFileJava = javaSourceDir + modGroupPath + "/" + mixinPluginPath + ".java"
|
|
String targetFileScala = scalaSourceDir + modGroupPath + "/" + mixinPluginPath + ".scala"
|
|
String targetFileScalaJava = scalaSourceDir + modGroupPath + "/" + mixinPluginPath + ".java"
|
|
String targetFileKotlin = kotlinSourceDir + modGroupPath + "/" + mixinPluginPath + ".kt"
|
|
if (!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) {
|
|
throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin)
|
|
}
|
|
}
|
|
}
|
|
|
|
if (coreModClass) {
|
|
final String coreModPath = coreModClass.toString().replaceAll("\\.", "/")
|
|
String targetFileJava = javaSourceDir + modGroupPath + "/" + coreModPath + ".java"
|
|
String targetFileScala = scalaSourceDir + modGroupPath + "/" + coreModPath + ".scala"
|
|
String targetFileScalaJava = scalaSourceDir + modGroupPath + "/" + coreModPath + ".java"
|
|
String targetFileKotlin = kotlinSourceDir + modGroupPath + "/" + coreModPath + ".kt"
|
|
if (!(getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists() || getFile(targetFileKotlin).exists())) {
|
|
throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava + " or " + targetFileKotlin)
|
|
}
|
|
}
|
|
|
|
configurations.configureEach {
|
|
resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS)
|
|
|
|
// Make sure GregTech build won't time out
|
|
System.setProperty("org.gradle.internal.http.connectionTimeout", 120000 as String)
|
|
System.setProperty("org.gradle.internal.http.socketTimeout", 120000 as String)
|
|
}
|
|
|
|
// Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version
|
|
try {
|
|
'git config core.fileMode false'.execute()
|
|
}
|
|
catch (Exception ignored) {
|
|
out.style(Style.Failure).println("git isn't installed at all")
|
|
}
|
|
|
|
// Pulls version first from the VERSION env and then git tag
|
|
String identifiedVersion
|
|
String versionOverride = System.getenv("VERSION") ?: null
|
|
try {
|
|
identifiedVersion = versionOverride == null ? gitVersion() : versionOverride
|
|
}
|
|
catch (Exception ignored) {
|
|
out.style(Style.Failure).text(
|
|
'This mod must be version controlled by Git AND the repository must provide at least one tag,\n' +
|
|
'or the VERSION override must be set! ').style(Style.SuccessHeader).text('(Do NOT download from GitHub using the ZIP option, instead\n' +
|
|
'clone the repository, see ').style(Style.Info).text('https://gtnh.miraheze.org/wiki/Development').style(Style.SuccessHeader).println(' for details.)'
|
|
)
|
|
versionOverride = 'NO-GIT-TAG-SET'
|
|
identifiedVersion = versionOverride
|
|
}
|
|
version = identifiedVersion
|
|
ext {
|
|
modVersion = identifiedVersion
|
|
}
|
|
|
|
if (identifiedVersion == versionOverride) {
|
|
out.style(Style.Failure).text('Override version to ').style(Style.Identifier).text(modVersion).style(Style.Failure).println('!\7')
|
|
}
|
|
|
|
group = "com.github.GTNewHorizons"
|
|
if (project.hasProperty("customArchiveBaseName") && customArchiveBaseName) {
|
|
archivesBaseName = customArchiveBaseName
|
|
} else {
|
|
archivesBaseName = modId
|
|
}
|
|
|
|
|
|
minecraft {
|
|
if (replaceGradleTokenInFile) {
|
|
for (f in replaceGradleTokenInFile.split(',')) {
|
|
tagReplacementFiles.add f
|
|
}
|
|
}
|
|
if (gradleTokenModId) {
|
|
injectedTags.put gradleTokenModId, modId
|
|
}
|
|
if (gradleTokenModName) {
|
|
injectedTags.put gradleTokenModName, modName
|
|
}
|
|
if (gradleTokenVersion) {
|
|
injectedTags.put gradleTokenVersion, modVersion
|
|
}
|
|
if (gradleTokenGroupName) {
|
|
injectedTags.put gradleTokenGroupName, modGroup
|
|
}
|
|
if (enableGenericInjection.toBoolean()) {
|
|
injectMissingGenerics.set(true)
|
|
}
|
|
|
|
username = developmentEnvironmentUserName.toString()
|
|
|
|
lwjgl3Version = "3.3.2"
|
|
|
|
// Enable assertions in the current mod
|
|
extraRunJvmArguments.add("-ea:${modGroup}")
|
|
|
|
if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) {
|
|
if (usesMixinDebug.toBoolean()) {
|
|
extraRunJvmArguments.addAll([
|
|
"-Dmixin.debug.countInjections=true",
|
|
"-Dmixin.debug.verbose=true",
|
|
"-Dmixin.debug.export=true"
|
|
])
|
|
}
|
|
}
|
|
|
|
// Blowdryer is present in some old mod builds, do not propagate it further as a dependency
|
|
// IC2 has no reobf jars in its Maven
|
|
groupsToExcludeFromAutoReobfMapping.addAll(["com.diffplug", "com.diffplug.durian", "net.industrial-craft"])
|
|
}
|
|
|
|
if (generateGradleTokenClass) {
|
|
tasks.injectTags.outputClassName.set(generateGradleTokenClass)
|
|
}
|
|
|
|
// Custom reobf auto-mappings
|
|
configurations.configureEach {
|
|
dependencies.configureEach { dep ->
|
|
if (dep instanceof org.gradle.api.artifacts.ExternalModuleDependency) {
|
|
if (dep.group == "net.industrial-craft" && dep.name == "industrialcraft-2") {
|
|
// https://www.curseforge.com/minecraft/mc-mods/industrial-craft/files/2353971
|
|
project.dependencies.reobfJarConfiguration("curse.maven:ic2-242638:2353971")
|
|
}
|
|
}
|
|
}
|
|
def obfuscationAttr = it.attributes.getAttribute(ObfuscationAttribute.OBFUSCATION_ATTRIBUTE)
|
|
if (obfuscationAttr != null && obfuscationAttr.name == ObfuscationAttribute.SRG) {
|
|
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
|
|
// Remap CoFH core cursemaven dev jar to the obfuscated version for runObfClient/Server
|
|
if (details.requested.group == 'curse.maven' && details.requested.name.endsWith('-69162') && details.requested.version == '2388751') {
|
|
details.useVersion '2388750'
|
|
details.because 'Pick obfuscated jar'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Ensure tests have access to minecraft classes
|
|
sourceSets {
|
|
test {
|
|
java {
|
|
compileClasspath += sourceSets.patchedMc.output + sourceSets.mcLauncher.output
|
|
runtimeClasspath += sourceSets.patchedMc.output + sourceSets.mcLauncher.output
|
|
}
|
|
}
|
|
}
|
|
|
|
if (file('addon.gradle').exists()) {
|
|
apply from: 'addon.gradle'
|
|
}
|
|
|
|
// Allow unsafe repos but warn
|
|
repositories.configureEach { repo ->
|
|
if (repo instanceof org.gradle.api.artifacts.repositories.UrlArtifactRepository) {
|
|
if (repo.getUrl() != null && repo.getUrl().getScheme() == "http" && !repo.allowInsecureProtocol) {
|
|
logger.warn("Deprecated: Allowing insecure connections for repo '${repo.name}' - add 'allowInsecureProtocol = true'")
|
|
repo.allowInsecureProtocol = true
|
|
}
|
|
}
|
|
}
|
|
|
|
apply from: 'repositories.gradle'
|
|
|
|
configurations {
|
|
runtimeClasspath.extendsFrom(runtimeOnlyNonPublishable)
|
|
testRuntimeClasspath.extendsFrom(runtimeOnlyNonPublishable)
|
|
for (config in [compileClasspath, runtimeClasspath, testCompileClasspath, testRuntimeClasspath]) {
|
|
if (usesShadowedDependencies.toBoolean()) {
|
|
config.extendsFrom(shadowImplementation)
|
|
// TODO: remove Compile after all uses are refactored to Implementation
|
|
config.extendsFrom(shadeCompile)
|
|
config.extendsFrom(shadowCompile)
|
|
}
|
|
}
|
|
// A "bag-of-dependencies"-style configuration for backwards compatibility, gets put in "api"
|
|
create("compile") {
|
|
description = "Deprecated: use api or implementation instead, gets put in api"
|
|
canBeConsumed = false
|
|
canBeResolved = false
|
|
visible = false
|
|
}
|
|
create("testCompile") {
|
|
description = "Deprecated: use testImplementation instead"
|
|
canBeConsumed = false
|
|
canBeResolved = false
|
|
visible = false
|
|
}
|
|
api.extendsFrom(compile)
|
|
testImplementation.extendsFrom(testCompile)
|
|
}
|
|
|
|
afterEvaluate {
|
|
if (!configurations.compile.allDependencies.empty || !configurations.testCompile.allDependencies.empty) {
|
|
logger.warn("This project uses deprecated `compile` dependencies, please migrate to using `api` and `implementation`")
|
|
logger.warn("For more details, see https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/master/dependencies.gradle")
|
|
}
|
|
}
|
|
|
|
repositories {
|
|
maven {
|
|
name 'Overmind forge repo mirror'
|
|
url 'https://gregtech.overminddl1.com/'
|
|
mavenContent {
|
|
excludeGroup("net.minecraftforge") // missing the `universal` artefact
|
|
}
|
|
}
|
|
maven {
|
|
name = "GTNH Maven"
|
|
url = "http://jenkins.usrv.eu:8081/nexus/content/groups/public/"
|
|
allowInsecureProtocol = true
|
|
}
|
|
maven {
|
|
name 'sonatype'
|
|
url 'https://oss.sonatype.org/content/repositories/snapshots/'
|
|
content {
|
|
includeGroup "org.lwjgl"
|
|
}
|
|
}
|
|
if (includeWellKnownRepositories.toBoolean()) {
|
|
maven {
|
|
name "CurseMaven"
|
|
url "https://cursemaven.com"
|
|
content {
|
|
includeGroup "curse.maven"
|
|
}
|
|
}
|
|
maven {
|
|
name = "ic2"
|
|
url = "https://maven.ic2.player.to/"
|
|
metadataSources {
|
|
mavenPom()
|
|
artifact()
|
|
}
|
|
}
|
|
maven {
|
|
name = "ic2-mirror"
|
|
url = "https://maven2.ic2.player.to/"
|
|
metadataSources {
|
|
mavenPom()
|
|
artifact()
|
|
}
|
|
}
|
|
maven {
|
|
name "MMD Maven"
|
|
url "https://maven.mcmoddev.com/"
|
|
}
|
|
}
|
|
}
|
|
|
|
def mixinProviderGroup = "io.github.legacymoddingmc"
|
|
def mixinProviderModule = "unimixins"
|
|
def mixinProviderVersion = "0.1.7.1"
|
|
def mixinProviderSpecNoClassifer = "${mixinProviderGroup}:${mixinProviderModule}:${mixinProviderVersion}"
|
|
def mixinProviderSpec = "${mixinProviderSpecNoClassifer}:dev"
|
|
ext.mixinProviderSpec = mixinProviderSpec
|
|
|
|
dependencies {
|
|
if (usesMixins.toBoolean()) {
|
|
annotationProcessor('org.ow2.asm:asm-debug-all:5.0.3')
|
|
annotationProcessor('com.google.guava:guava:24.1.1-jre')
|
|
annotationProcessor('com.google.code.gson:gson:2.8.6')
|
|
annotationProcessor(mixinProviderSpec)
|
|
if (usesMixinDebug.toBoolean()) {
|
|
runtimeOnlyNonPublishable('org.jetbrains:intellij-fernflower:1.2.1.16')
|
|
}
|
|
}
|
|
if (usesMixins.toBoolean()) {
|
|
implementation(mixinProviderSpec)
|
|
} else if (forceEnableMixins.toBoolean()) {
|
|
runtimeOnlyNonPublishable(mixinProviderSpec)
|
|
}
|
|
}
|
|
|
|
pluginManager.withPlugin('org.jetbrains.kotlin.kapt') {
|
|
if (usesMixins.toBoolean()) {
|
|
dependencies {
|
|
kapt(mixinProviderSpec)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Replace old mixin mods with unimixins
|
|
// https://docs.gradle.org/8.0.2/userguide/resolution_rules.html#sec:substitution_with_classifier
|
|
configurations.all {
|
|
resolutionStrategy.dependencySubstitution {
|
|
substitute module('com.gtnewhorizon:gtnhmixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods")
|
|
substitute module('com.github.GTNewHorizons:Mixingasm') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods")
|
|
substitute module('com.github.GTNewHorizons:SpongePoweredMixin') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods")
|
|
substitute module('com.github.GTNewHorizons:SpongeMixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Unimixins replaces other mixin mods")
|
|
substitute module('io.github.legacymoddingmc:unimixins') using module(mixinProviderSpecNoClassifer) withClassifier("dev") because("Our previous unimixins upload was missing the dev classifier")
|
|
}
|
|
}
|
|
|
|
apply from: 'dependencies.gradle'
|
|
|
|
def mixingConfigRefMap = 'mixins.' + modId + '.refmap.json'
|
|
def mixinTmpDir = buildDir.path + File.separator + 'tmp' + File.separator + 'mixins'
|
|
def refMap = "${mixinTmpDir}" + File.separator + mixingConfigRefMap
|
|
def mixinSrg = "${mixinTmpDir}" + File.separator + "mixins.srg"
|
|
|
|
tasks.register('generateAssets') {
|
|
group = "GTNH Buildscript"
|
|
description = "Generates a mixin config file at /src/main/resources/mixins.modid.json if needed"
|
|
onlyIf { usesMixins.toBoolean() }
|
|
doLast {
|
|
def mixinConfigFile = getFile("/src/main/resources/mixins." + modId + ".json")
|
|
if (!mixinConfigFile.exists()) {
|
|
def mixinPluginLine = ""
|
|
if (!mixinPlugin.isEmpty()) {
|
|
// We might not have a mixin plugin if we're using early/late mixins
|
|
mixinPluginLine += """\n "plugin": "${modGroup}.${mixinPlugin}", """
|
|
}
|
|
|
|
mixinConfigFile.text = """{
|
|
"required": true,
|
|
"minVersion": "0.8.5-GTNH",
|
|
"package": "${modGroup}.${mixinsPackage}",${mixinPluginLine}
|
|
"refmap": "${mixingConfigRefMap}",
|
|
"target": "@env(DEFAULT)",
|
|
"compatibilityLevel": "JAVA_8",
|
|
"mixins": [],
|
|
"client": [],
|
|
"server": []
|
|
}
|
|
"""
|
|
}
|
|
}
|
|
}
|
|
|
|
if (usesMixins.toBoolean()) {
|
|
tasks.named("reobfJar", ReobfuscatedJar).configure {
|
|
extraSrgFiles.from(mixinSrg)
|
|
}
|
|
|
|
tasks.named("processResources").configure {
|
|
dependsOn("generateAssets")
|
|
}
|
|
|
|
tasks.named("compileJava", JavaCompile).configure {
|
|
doFirst {
|
|
new File(mixinTmpDir).mkdirs()
|
|
}
|
|
options.compilerArgs += [
|
|
"-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}",
|
|
"-AoutSrgFile=${mixinSrg}",
|
|
"-AoutRefMapFile=${refMap}",
|
|
// Elan: from what I understand they are just some linter configs so you get some warning on how to properly code
|
|
"-XDenableSunApiLintControl",
|
|
"-XDignore.symbol.file"
|
|
]
|
|
}
|
|
|
|
pluginManager.withPlugin('org.jetbrains.kotlin.kapt') {
|
|
kapt {
|
|
correctErrorTypes = true
|
|
javacOptions {
|
|
option("-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}")
|
|
option("-AoutSrgFile=$mixinSrg")
|
|
option("-AoutRefMapFile=$refMap")
|
|
}
|
|
}
|
|
tasks.configureEach { task ->
|
|
if (task.name == "kaptKotlin") {
|
|
task.doFirst {
|
|
new File(mixinTmpDir).mkdirs()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
tasks.named("processResources", ProcessResources).configure {
|
|
// this will ensure that this task is redone when the versions change.
|
|
inputs.property "version", project.version
|
|
inputs.property "mcversion", project.minecraft.mcVersion
|
|
exclude("spotless.gradle")
|
|
|
|
// replace stuff in mcmod.info, nothing else. replaces ${key} with value in text
|
|
filesMatching("mcmod.info") {
|
|
expand "minecraftVersion": project.minecraft.mcVersion,
|
|
"modVersion": modVersion,
|
|
"modId": modId,
|
|
"modName": modName
|
|
}
|
|
|
|
if (usesMixins.toBoolean()) {
|
|
from refMap
|
|
dependsOn("compileJava", "compileScala")
|
|
}
|
|
}
|
|
|
|
ext.java17Toolchain = (JavaToolchainSpec spec) -> {
|
|
spec.languageVersion.set(JavaLanguageVersion.of(17))
|
|
spec.vendor.set(JvmVendorSpec.matching("jetbrains"))
|
|
}
|
|
|
|
ext.java17DependenciesCfg = configurations.create("java17Dependencies") {
|
|
extendsFrom(configurations.getByName("runtimeClasspath")) // Ensure consistent transitive dependency resolution
|
|
canBeConsumed = false
|
|
}
|
|
ext.java17PatchDependenciesCfg = configurations.create("java17PatchDependencies") {
|
|
canBeConsumed = false
|
|
}
|
|
|
|
dependencies {
|
|
def lwjgl3ifyVersion = '1.3.5'
|
|
def asmVersion = '9.4'
|
|
if (modId != 'lwjgl3ify') {
|
|
java17Dependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}")
|
|
}
|
|
if (modId != 'hodgepodge') {
|
|
java17Dependencies('com.github.GTNewHorizons:Hodgepodge:2.2.13')
|
|
}
|
|
|
|
java17PatchDependencies('net.minecraft:launchwrapper:1.15') {transitive = false}
|
|
java17PatchDependencies("org.ow2.asm:asm:${asmVersion}")
|
|
java17PatchDependencies("org.ow2.asm:asm-commons:${asmVersion}")
|
|
java17PatchDependencies("org.ow2.asm:asm-tree:${asmVersion}")
|
|
java17PatchDependencies("org.ow2.asm:asm-analysis:${asmVersion}")
|
|
java17PatchDependencies("org.ow2.asm:asm-util:${asmVersion}")
|
|
java17PatchDependencies('org.ow2.asm:asm-deprecated:7.1')
|
|
java17PatchDependencies("org.apache.commons:commons-lang3:3.12.0")
|
|
java17PatchDependencies("com.github.GTNewHorizons:lwjgl3ify:${lwjgl3ifyVersion}:forgePatches") {transitive = false}
|
|
}
|
|
|
|
ext.java17JvmArgs = [
|
|
// Java 9+ support
|
|
"--illegal-access=warn",
|
|
"-Djava.security.manager=allow",
|
|
"-Dfile.encoding=UTF-8",
|
|
"--add-opens", "java.base/jdk.internal.loader=ALL-UNNAMED",
|
|
"--add-opens", "java.base/java.net=ALL-UNNAMED",
|
|
"--add-opens", "java.base/java.nio=ALL-UNNAMED",
|
|
"--add-opens", "java.base/java.io=ALL-UNNAMED",
|
|
"--add-opens", "java.base/java.lang=ALL-UNNAMED",
|
|
"--add-opens", "java.base/java.lang.reflect=ALL-UNNAMED",
|
|
"--add-opens", "java.base/java.text=ALL-UNNAMED",
|
|
"--add-opens", "java.base/java.util=ALL-UNNAMED",
|
|
"--add-opens", "java.base/jdk.internal.reflect=ALL-UNNAMED",
|
|
"--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED",
|
|
"--add-opens", "jdk.naming.dns/com.sun.jndi.dns=ALL-UNNAMED,java.naming",
|
|
"--add-opens", "java.desktop/sun.awt.image=ALL-UNNAMED",
|
|
"--add-modules", "jdk.dynalink",
|
|
"--add-opens", "jdk.dynalink/jdk.dynalink.beans=ALL-UNNAMED",
|
|
"--add-modules", "java.sql.rowset",
|
|
"--add-opens", "java.sql.rowset/javax.sql.rowset.serial=ALL-UNNAMED"
|
|
]
|
|
|
|
ext.hotswapJvmArgs = [
|
|
// DCEVM advanced hot reload
|
|
"-XX:+AllowEnhancedClassRedefinition",
|
|
"-XX:HotswapAgent=fatjar"
|
|
]
|
|
|
|
ext.setupHotswapAgentTask = tasks.register("setupHotswapAgent") {
|
|
group = "GTNH Buildscript"
|
|
description = "Installs a recent version of HotSwapAgent into the Java 17 JetBrains runtime directory"
|
|
def hsaUrl = 'https://github.com/HotswapProjects/HotswapAgent/releases/download/1.4.2-SNAPSHOT/hotswap-agent-1.4.2-SNAPSHOT.jar'
|
|
def targetFolderProvider = javaToolchains.launcherFor(java17Toolchain).map {it.metadata.installationPath.dir("lib/hotswap")}
|
|
def targetFilename = "hotswap-agent.jar"
|
|
onlyIf {
|
|
!targetFolderProvider.get().file(targetFilename).asFile.exists()
|
|
}
|
|
doLast {
|
|
def targetFolder = targetFolderProvider.get()
|
|
targetFolder.asFile.mkdirs()
|
|
download.run {
|
|
src hsaUrl
|
|
dest targetFolder.file(targetFilename).asFile
|
|
overwrite false
|
|
tempAndMove true
|
|
}
|
|
}
|
|
}
|
|
|
|
public abstract class RunHotswappableMinecraftTask extends RunMinecraftTask {
|
|
// IntelliJ doesn't seem to allow commandline arguments so we also support an env variable
|
|
private boolean enableHotswap = Boolean.valueOf(System.getenv("HOTSWAP"));
|
|
|
|
@Input
|
|
public boolean getEnableHotswap() { return enableHotswap }
|
|
@Option(option = "hotswap", description = "Enables HotSwapAgent for enhanced class reloading under a debugger")
|
|
public boolean setEnableHotswap(boolean enable) { enableHotswap = enable }
|
|
|
|
@Inject
|
|
public RunHotswappableMinecraftTask(Distribution side, String superTask, org.gradle.api.invocation.Gradle gradle) {
|
|
super(side, gradle)
|
|
|
|
this.lwjglVersion = 3
|
|
this.javaLauncher = project.javaToolchains.launcherFor(project.java17Toolchain)
|
|
this.extraJvmArgs.addAll(project.java17JvmArgs)
|
|
this.extraJvmArgs.addAll(project.provider(() -> enableHotswap ? project.hotswapJvmArgs : []))
|
|
|
|
this.classpath(project.java17PatchDependenciesCfg)
|
|
if (side == Distribution.CLIENT) {
|
|
this.classpath(project.minecraftTasks.lwjgl3Configuration)
|
|
}
|
|
// Use a raw provider instead of map to not create a dependency on the task
|
|
this.classpath(project.provider(() -> project.tasks.named(superTask, RunMinecraftTask).get().classpath))
|
|
this.classpath.filter { file ->
|
|
!file.path.contains("2.9.4-nightly-20150209") // Remove lwjgl2
|
|
}
|
|
this.classpath(project.java17DependenciesCfg)
|
|
}
|
|
|
|
public void setup(Project project) {
|
|
super.setup(project)
|
|
if (project.usesMixins.toBoolean()) {
|
|
this.extraJvmArgs.addAll(project.provider(() -> {
|
|
def mixinCfg = project.configurations.detachedConfiguration(project.dependencies.create(project.mixinProviderSpec))
|
|
mixinCfg.canBeConsumed = false
|
|
mixinCfg.transitive = false
|
|
enableHotswap ? ["-javaagent:" + mixinCfg.singleFile.absolutePath] : []
|
|
}))
|
|
}
|
|
}
|
|
}
|
|
|
|
def runClient17Task = tasks.register("runClient17", RunHotswappableMinecraftTask, Distribution.CLIENT, "runClient")
|
|
runClient17Task.configure {
|
|
setup(project)
|
|
group = "Modded Minecraft"
|
|
description = "Runs the modded client using Java 17, lwjgl3ify and Hodgepodge"
|
|
dependsOn(setupHotswapAgentTask, mcpTasks.launcherSources.classesTaskName, minecraftTasks.taskDownloadVanillaAssets, mcpTasks.taskPackagePatchedMc, 'jar')
|
|
mainClass = "GradleStart"
|
|
username = minecraft.username
|
|
userUUID = minecraft.userUUID
|
|
}
|
|
|
|
def runServer17Task = tasks.register("runServer17", RunHotswappableMinecraftTask, Distribution.DEDICATED_SERVER, "runServer")
|
|
runServer17Task.configure {
|
|
setup(project)
|
|
group = "Modded Minecraft"
|
|
description = "Runs the modded server using Java 17, lwjgl3ify and Hodgepodge"
|
|
dependsOn(setupHotswapAgentTask, mcpTasks.launcherSources.classesTaskName, minecraftTasks.taskDownloadVanillaAssets, mcpTasks.taskPackagePatchedMc, 'jar')
|
|
mainClass = "GradleStartServer"
|
|
extraArgs.add("nogui")
|
|
}
|
|
|
|
def getManifestAttributes() {
|
|
def manifestAttributes = [:]
|
|
if (!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) {
|
|
manifestAttributes += ["FMLCorePluginContainsFMLMod": true]
|
|
}
|
|
|
|
if (accessTransformersFile) {
|
|
manifestAttributes += ["FMLAT": accessTransformersFile.toString()]
|
|
}
|
|
|
|
if (coreModClass) {
|
|
manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass]
|
|
}
|
|
|
|
if (usesMixins.toBoolean()) {
|
|
manifestAttributes += [
|
|
"TweakClass" : "org.spongepowered.asm.launch.MixinTweaker",
|
|
"MixinConfigs" : "mixins." + modId + ".json",
|
|
"ForceLoadAsMod": !containsMixinsAndOrCoreModOnly.toBoolean()
|
|
]
|
|
}
|
|
return manifestAttributes
|
|
}
|
|
|
|
tasks.named("jar", Jar).configure {
|
|
manifest {
|
|
attributes(getManifestAttributes())
|
|
}
|
|
}
|
|
|
|
if (usesShadowedDependencies.toBoolean()) {
|
|
tasks.named("shadowJar", ShadowJar).configure {
|
|
manifest {
|
|
attributes(getManifestAttributes())
|
|
}
|
|
|
|
if (minimizeShadowedDependencies.toBoolean()) {
|
|
minimize() // This will only allow shading for actually used classes
|
|
}
|
|
configurations = [
|
|
project.configurations.shadowImplementation,
|
|
project.configurations.shadowCompile,
|
|
project.configurations.shadeCompile
|
|
]
|
|
archiveClassifier.set('dev')
|
|
if (relocateShadowedDependencies.toBoolean()) {
|
|
relocationPrefix = modGroup + ".shadow"
|
|
enableRelocation = true
|
|
}
|
|
}
|
|
configurations.runtimeElements.outgoing.artifacts.clear()
|
|
configurations.apiElements.outgoing.artifacts.clear()
|
|
configurations.runtimeElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar))
|
|
configurations.apiElements.outgoing.artifact(tasks.named("shadowJar", ShadowJar))
|
|
tasks.named("jar", Jar) {
|
|
enabled = false
|
|
finalizedBy(tasks.shadowJar)
|
|
}
|
|
tasks.named("reobfJar", ReobfuscatedJar) {
|
|
inputJar.set(tasks.named("shadowJar", ShadowJar).flatMap({it.archiveFile}))
|
|
}
|
|
AdhocComponentWithVariants javaComponent = (AdhocComponentWithVariants) project.components.findByName("java")
|
|
javaComponent.withVariantsFromConfiguration(configurations.shadowRuntimeElements) {
|
|
skip()
|
|
}
|
|
for (runTask in ["runClient", "runServer", "runClient17", "runServer17"]) {
|
|
tasks.named(runTask).configure {
|
|
dependsOn("shadowJar")
|
|
}
|
|
}
|
|
}
|
|
ext.publishableDevJar = usesShadowedDependencies.toBoolean() ? tasks.shadowJar : tasks.jar
|
|
ext.publishableObfJar = tasks.reobfJar
|
|
|
|
tasks.register('apiJar', Jar) {
|
|
from(sourceSets.main.allSource) {
|
|
include modGroupPath + "/" + apiPackagePath + '/**'
|
|
}
|
|
|
|
from(sourceSets.main.output) {
|
|
include modGroupPath + "/" + apiPackagePath + '/**'
|
|
}
|
|
|
|
from(sourceSets.main.resources.srcDirs) {
|
|
include("LICENSE")
|
|
}
|
|
|
|
getArchiveClassifier().set('api')
|
|
}
|
|
|
|
artifacts {
|
|
if (!noPublishedSources) {
|
|
archives tasks.named("sourcesJar")
|
|
}
|
|
if (apiPackage) {
|
|
archives tasks.named("apiJar")
|
|
}
|
|
}
|
|
|
|
idea {
|
|
module {
|
|
downloadJavadoc = true
|
|
downloadSources = true
|
|
inheritOutputDirs = true
|
|
}
|
|
project {
|
|
settings {
|
|
if (ideaOverrideBuildType != "") {
|
|
delegateActions {
|
|
if ("gradle".equalsIgnoreCase(ideaOverrideBuildType)) {
|
|
delegateBuildRunToGradle = true
|
|
testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.GRADLE
|
|
} else if ("idea".equalsIgnoreCase(ideaOverrideBuildType)) {
|
|
delegateBuildRunToGradle = false
|
|
testRunner = org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.PLATFORM
|
|
} else {
|
|
throw GradleScriptException('Accepted value for ideaOverrideBuildType is one of gradle or idea.')
|
|
}
|
|
}
|
|
}
|
|
runConfigurations {
|
|
"1. Run Client"(Gradle) {
|
|
taskNames = ["runClient"]
|
|
}
|
|
"2. Run Server"(Gradle) {
|
|
taskNames = ["runServer"]
|
|
}
|
|
"1a. Run Client (Java 17)"(Gradle) {
|
|
taskNames = ["runClient17"]
|
|
}
|
|
"2a. Run Server (Java 17)"(Gradle) {
|
|
taskNames = ["runServer17"]
|
|
}
|
|
"1b. Run Client (Java 17, Hotswap)"(Gradle) {
|
|
taskNames = ["runClient17"]
|
|
envs = ["HOTSWAP": "true"]
|
|
}
|
|
"2b. Run Server (Java 17, Hotswap)"(Gradle) {
|
|
taskNames = ["runServer17"]
|
|
envs = ["HOTSWAP": "true"]
|
|
}
|
|
"3. Run Obfuscated Client"(Gradle) {
|
|
taskNames = ["runObfClient"]
|
|
}
|
|
"4. Run Obfuscated Server"(Gradle) {
|
|
taskNames = ["runObfServer"]
|
|
}
|
|
if (!disableSpotless) {
|
|
"5. Apply spotless"(Gradle) {
|
|
taskNames = ["spotlessApply"]
|
|
}
|
|
}
|
|
def coreModArgs = ""
|
|
if (coreModClass) {
|
|
coreModArgs = ' "-Dfml.coreMods.load=' + modGroup + '.' + coreModClass + '"'
|
|
}
|
|
"Run Client (IJ Native)"(Application) {
|
|
mainClass = "GradleStart"
|
|
moduleName = project.name + ".ideVirtualMain"
|
|
afterEvaluate {
|
|
workingDirectory = tasks.runClient.workingDir.absolutePath
|
|
programParameters = tasks.runClient.calculateArgs(project).collect { '"' + it + '"' }.join(' ')
|
|
jvmArgs = tasks.runClient.calculateJvmArgs(project).collect { '"' + it + '"' }.join(' ') +
|
|
' ' + tasks.runClient.systemProperties.collect { '"-D' + it.key + '=' + it.value.toString() + '"' }.join(' ') +
|
|
coreModArgs
|
|
}
|
|
}
|
|
"Run Server (IJ Native)"(Application) {
|
|
mainClass = "GradleStartServer"
|
|
moduleName = project.name + ".ideVirtualMain"
|
|
afterEvaluate {
|
|
workingDirectory = tasks.runServer.workingDir.absolutePath
|
|
programParameters = tasks.runServer.calculateArgs(project).collect { '"' + it + '"' }.join(' ')
|
|
jvmArgs = tasks.runServer.calculateJvmArgs(project).collect { '"' + it + '"' }.join(' ') +
|
|
' ' + tasks.runServer.systemProperties.collect { '"-D' + it.key + '=' + it.value.toString() + '"' }.join(' ') +
|
|
coreModArgs
|
|
}
|
|
}
|
|
}
|
|
compiler.javac {
|
|
afterEvaluate {
|
|
javacAdditionalOptions = "-encoding utf8"
|
|
moduleJavacAdditionalOptions = [
|
|
(project.name + ".main"): tasks.compileJava.options.compilerArgs.collect { '"' + it + '"' }.join(' ')
|
|
]
|
|
}
|
|
}
|
|
withIDEADir { File ideaDir ->
|
|
if (!ideaDir.path.contains(".idea")) {
|
|
// If an .ipr file exists, the project root directory is passed here instead of the .idea subdirectory
|
|
ideaDir = new File(ideaDir, ".idea")
|
|
}
|
|
if (ideaDir.isDirectory()) {
|
|
def miscFile = new File(ideaDir, "misc.xml")
|
|
if (miscFile.isFile()) {
|
|
boolean dirty = false
|
|
def miscTransformer = new XmlTransformer()
|
|
miscTransformer.addAction { root ->
|
|
Node rootNode = root.asNode()
|
|
def rootManager = rootNode
|
|
.component.find { it.@name == 'ProjectRootManager' }
|
|
if (!rootManager) {
|
|
rootManager = rootNode.appendNode('component', ['name': 'ProjectRootManager', 'version': '2'])
|
|
dirty = true
|
|
}
|
|
def output = rootManager.output
|
|
if (!output) {
|
|
output = rootManager.appendNode('output')
|
|
dirty = true
|
|
}
|
|
if (!output.@url) {
|
|
// Only modify the output url if it doesn't yet have one, or if the existing one is blank somehow.
|
|
// This is a sensible default for most setups
|
|
output.@url = 'file://$PROJECT_DIR$/build/ideaBuild'
|
|
dirty = true
|
|
}
|
|
}
|
|
def result = miscTransformer.transform(miscFile.text)
|
|
if (dirty) {
|
|
miscFile.write(result)
|
|
}
|
|
} else {
|
|
miscFile.text = """<?xml version="1.0" encoding="UTF-8"?>
|
|
<project version="4">
|
|
<component name="ProjectRootManager" version="2">
|
|
<output url="file://\$PROJECT_DIR\$/out" />
|
|
</component>
|
|
</project>
|
|
"""
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
tasks.named("processIdeaSettings").configure {
|
|
dependsOn("injectTags")
|
|
}
|
|
|
|
// workaround variable hiding in pom processing
|
|
def projectConfigs = project.configurations
|
|
|
|
publishing {
|
|
publications {
|
|
create("maven", MavenPublication) {
|
|
from components.java
|
|
|
|
if (apiPackage) {
|
|
artifact apiJar
|
|
}
|
|
|
|
groupId = System.getenv("ARTIFACT_GROUP_ID") ?: project.group
|
|
artifactId = System.getenv("ARTIFACT_ID") ?: project.name
|
|
// Using the identified version, not project.version as it has the prepended 1.7.10
|
|
version = System.getenv("RELEASE_VERSION") ?: identifiedVersion
|
|
}
|
|
}
|
|
|
|
repositories {
|
|
maven {
|
|
url = "http://jenkins.usrv.eu:8081/nexus/content/repositories/releases"
|
|
allowInsecureProtocol = true
|
|
credentials {
|
|
username = System.getenv("MAVEN_USER") ?: "NONE"
|
|
password = System.getenv("MAVEN_PASSWORD") ?: "NONE"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (modrinthProjectId.size() != 0 && System.getenv("MODRINTH_TOKEN") != null) {
|
|
apply plugin: 'com.modrinth.minotaur'
|
|
|
|
File changelogFile = new File(System.getenv("CHANGELOG_FILE") ?: "CHANGELOG.md")
|
|
|
|
modrinth {
|
|
token = System.getenv("MODRINTH_TOKEN")
|
|
projectId = modrinthProjectId
|
|
versionNumber = identifiedVersion
|
|
versionType = identifiedVersion.endsWith("-pre") ? "beta" : "release"
|
|
changelog = changelogFile.exists() ? changelogFile.getText("UTF-8") : ""
|
|
uploadFile = publishableObfJar
|
|
additionalFiles = getSecondaryArtifacts()
|
|
gameVersions = [minecraftVersion]
|
|
loaders = ["forge"]
|
|
debugMode = false
|
|
}
|
|
|
|
if (modrinthRelations.size() != 0) {
|
|
String[] deps = modrinthRelations.split(";")
|
|
deps.each { dep ->
|
|
if (dep.size() == 0) {
|
|
return
|
|
}
|
|
String[] parts = dep.split(":")
|
|
String[] qual = parts[0].split("-")
|
|
addModrinthDep(qual[0], qual[1], parts[1])
|
|
}
|
|
}
|
|
if (usesMixins.toBoolean()) {
|
|
addModrinthDep("required", "project", "unimixins")
|
|
}
|
|
tasks.modrinth.dependsOn(build)
|
|
tasks.publish.dependsOn(tasks.modrinth)
|
|
}
|
|
|
|
if (curseForgeProjectId.size() != 0 && System.getenv("CURSEFORGE_TOKEN") != null) {
|
|
apply plugin: 'com.matthewprenger.cursegradle'
|
|
|
|
File changelogFile = new File(System.getenv("CHANGELOG_FILE") ?: "CHANGELOG.md")
|
|
|
|
curseforge {
|
|
apiKey = System.getenv("CURSEFORGE_TOKEN")
|
|
project {
|
|
id = curseForgeProjectId
|
|
if (changelogFile.exists()) {
|
|
changelogType = "markdown"
|
|
changelog = changelogFile
|
|
}
|
|
releaseType = identifiedVersion.endsWith("-pre") ? "beta" : "release"
|
|
addGameVersion minecraftVersion
|
|
addGameVersion "Forge"
|
|
mainArtifact publishableObfJar
|
|
for (artifact in getSecondaryArtifacts()) addArtifact artifact
|
|
}
|
|
|
|
options {
|
|
javaIntegration = false
|
|
forgeGradleIntegration = false
|
|
debug = false
|
|
}
|
|
}
|
|
|
|
if (curseForgeRelations.size() != 0) {
|
|
String[] deps = curseForgeRelations.split(";")
|
|
deps.each { dep ->
|
|
if (dep.size() == 0) {
|
|
return
|
|
}
|
|
String[] parts = dep.split(":")
|
|
addCurseForgeRelation(parts[0], parts[1])
|
|
}
|
|
}
|
|
if (usesMixins.toBoolean()) {
|
|
addCurseForgeRelation("requiredDependency", "unimixins")
|
|
}
|
|
tasks.curseforge.dependsOn(build)
|
|
tasks.publish.dependsOn(tasks.curseforge)
|
|
}
|
|
|
|
def addModrinthDep(String scope, String type, String name) {
|
|
com.modrinth.minotaur.dependencies.Dependency dep;
|
|
if (!(scope in ["required", "optional", "incompatible", "embedded"])) {
|
|
throw new Exception("Invalid modrinth dependency scope: " + scope)
|
|
}
|
|
switch (type) {
|
|
case "project":
|
|
dep = new ModDependency(name, scope)
|
|
break
|
|
case "version":
|
|
dep = new VersionDependency(name, scope)
|
|
break
|
|
default:
|
|
throw new Exception("Invalid modrinth dependency type: " + type)
|
|
}
|
|
project.modrinth.dependencies.add(dep)
|
|
}
|
|
|
|
def addCurseForgeRelation(String type, String name) {
|
|
if (!(type in ["requiredDependency", "embeddedLibrary", "optionalDependency", "tool", "incompatible"])) {
|
|
throw new Exception("Invalid CurseForge relation type: " + type)
|
|
}
|
|
CurseArtifact artifact = project.curseforge.curseProjects[0].mainArtifact
|
|
CurseRelation rel = (artifact.curseRelations ?: (artifact.curseRelations = new CurseRelation()))
|
|
rel."$type"(name)
|
|
}
|
|
|
|
// Updating
|
|
|
|
def buildscriptGradleVersion = "8.1.1"
|
|
|
|
tasks.named('wrapper', Wrapper).configure {
|
|
gradleVersion = buildscriptGradleVersion
|
|
}
|
|
|
|
tasks.register('updateBuildScript') {
|
|
group = 'GTNH Buildscript'
|
|
description = 'Updates the build script to the latest version'
|
|
|
|
if (gradle.gradleVersion != buildscriptGradleVersion && !Boolean.getBoolean('DISABLE_BUILDSCRIPT_GRADLE_UPDATE')) {
|
|
dependsOn('wrapper')
|
|
}
|
|
|
|
doLast {
|
|
if (performBuildScriptUpdate()) return
|
|
|
|
print("Build script already up-to-date!")
|
|
}
|
|
}
|
|
|
|
if (!project.getGradle().startParameter.isOffline() && !Boolean.getBoolean('DISABLE_BUILDSCRIPT_UPDATE_CHECK') && isNewBuildScriptVersionAvailable()) {
|
|
if (autoUpdateBuildScript.toBoolean()) {
|
|
performBuildScriptUpdate()
|
|
} else {
|
|
out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'")
|
|
if (gradle.gradleVersion != buildscriptGradleVersion) {
|
|
out.style(Style.SuccessHeader).println("updateBuildScript can update gradle from ${gradle.gradleVersion} to ${buildscriptGradleVersion}\n")
|
|
}
|
|
}
|
|
}
|
|
|
|
// If you want to add more cases to this task, implement them as arguments if total amount to print gets too large
|
|
tasks.register('faq') {
|
|
group = 'GTNH Buildscript'
|
|
description = 'Prints frequently asked questions about building a project'
|
|
|
|
doLast {
|
|
print("If your build fails to fetch dependencies, run './gradlew updateDependencies'. " +
|
|
"Or you can manually check if the versions are still on the distributing sites - " +
|
|
"the links can be found in repositories.gradle and build.gradle:repositories, " +
|
|
"but not build.gradle:buildscript.repositories - those ones are for gradle plugin metadata.\n\n" +
|
|
"If your build fails to recognize the syntax of new Java versions, enable Jabel in your " +
|
|
"gradle.properties. See how it's done in GTNH ExampleMod/gradle.properties. " +
|
|
"However, keep in mind that Jabel enables only syntax features, but not APIs that were introduced in " +
|
|
"Java 9 or later.")
|
|
}
|
|
}
|
|
|
|
static URL availableBuildScriptUrl() {
|
|
new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/build.gradle")
|
|
}
|
|
|
|
static URL exampleSettingsGradleUrl() {
|
|
new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/settings.gradle.example")
|
|
}
|
|
|
|
static URL exampleGitAttributesUrl() {
|
|
new URL("https://raw.githubusercontent.com/GTNewHorizons/ExampleMod1.7.10/master/.gitattributes")
|
|
}
|
|
|
|
|
|
boolean verifyGitAttributes() {
|
|
def gitattributesFile = getFile(".gitattributes")
|
|
if (!gitattributesFile.exists()) {
|
|
println("Downloading default .gitattributes")
|
|
exampleGitAttributesUrl().withInputStream { i -> gitattributesFile.withOutputStream { it << i } }
|
|
exec {
|
|
workingDir '.'
|
|
commandLine 'git', 'add', '--renormalize', '.'
|
|
}
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
boolean verifySettingsGradle() {
|
|
def settingsFile = getFile("settings.gradle")
|
|
if (!settingsFile.exists()) {
|
|
println("Downloading default settings.gradle")
|
|
exampleSettingsGradleUrl().withInputStream { i -> settingsFile.withOutputStream { it << i } }
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
boolean performBuildScriptUpdate() {
|
|
if (isNewBuildScriptVersionAvailable()) {
|
|
def buildscriptFile = getFile("build.gradle")
|
|
availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } }
|
|
def out = services.get(StyledTextOutputFactory).create('buildscript-update-output')
|
|
out.style(Style.Success).print("Build script updated. Please REIMPORT the project or RESTART your IDE!")
|
|
boolean settingsupdated = verifySettingsGradle()
|
|
settingsupdated = verifyGitAttributes() || settingsupdated
|
|
if (settingsupdated)
|
|
throw new GradleException("Settings has been updated, please re-run task.")
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
boolean isNewBuildScriptVersionAvailable() {
|
|
Map parameters = ["connectTimeout": 2000, "readTimeout": 2000]
|
|
|
|
String currentBuildScript = getFile("build.gradle").getText()
|
|
String currentBuildScriptHash = getVersionHash(currentBuildScript)
|
|
String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText()
|
|
String availableBuildScriptHash = getVersionHash(availableBuildScript)
|
|
|
|
boolean isUpToDate = currentBuildScriptHash.empty || availableBuildScriptHash.empty || currentBuildScriptHash == availableBuildScriptHash
|
|
return !isUpToDate
|
|
}
|
|
|
|
static String getVersionHash(String buildScriptContent) {
|
|
String versionLine = buildScriptContent.find("^//version: [a-z0-9]*")
|
|
if (versionLine != null) {
|
|
return versionLine.split(": ").last()
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// Parameter Deobfuscation
|
|
|
|
tasks.register('deobfParams') {
|
|
group = 'GTNH Buildscript'
|
|
description = 'Rename all obfuscated parameter names inherited from Minecraft classes'
|
|
doLast { // TODO
|
|
|
|
String mcpDir = "$project.gradle.gradleUserHomeDir/caches/minecraft/de/oceanlabs/mcp/mcp_$channel/$mappingsVersion"
|
|
String mcpZIP = "$mcpDir/mcp_$channel-$mappingsVersion-${minecraftVersion}.zip"
|
|
String paramsCSV = "$mcpDir/params.csv"
|
|
|
|
download.run {
|
|
src "https://maven.minecraftforge.net/de/oceanlabs/mcp/mcp_$channel/$mappingsVersion-$minecraftVersion/mcp_$channel-$mappingsVersion-${minecraftVersion}.zip"
|
|
dest mcpZIP
|
|
overwrite false
|
|
}
|
|
|
|
if (!file(paramsCSV).exists()) {
|
|
println("Extracting MCP archive ...")
|
|
copy {
|
|
from(zipTree(mcpZIP))
|
|
into(mcpDir)
|
|
}
|
|
}
|
|
|
|
println("Parsing params.csv ...")
|
|
Map<String, String> params = new HashMap<>()
|
|
Files.lines(Paths.get(paramsCSV)).forEach { line ->
|
|
String[] cells = line.split(",")
|
|
if (cells.length > 2 && cells[0].matches("p_i?\\d+_\\d+_")) {
|
|
params.put(cells[0], cells[1])
|
|
}
|
|
}
|
|
|
|
out.style(Style.Success).println("Modified ${replaceParams(file("$projectDir/src/main/java"), params)} files!")
|
|
out.style(Style.Failure).println("Don't forget to verify that the code still works as before!\n It could be broken due to duplicate variables existing now\n or parameters taking priority over other variables.")
|
|
}
|
|
}
|
|
|
|
static int replaceParams(File file, Map<String, String> params) {
|
|
int fileCount = 0
|
|
|
|
if (file.isDirectory()) {
|
|
for (File f : file.listFiles()) {
|
|
fileCount += replaceParams(f, params)
|
|
}
|
|
return fileCount
|
|
}
|
|
println("Visiting ${file.getName()} ...")
|
|
try {
|
|
String content = new String(Files.readAllBytes(file.toPath()))
|
|
int hash = content.hashCode()
|
|
params.forEach { key, value ->
|
|
content = content.replaceAll(key, value)
|
|
}
|
|
if (hash != content.hashCode()) {
|
|
Files.write(file.toPath(), content.getBytes("UTF-8"))
|
|
return 1
|
|
}
|
|
} catch (Exception e) {
|
|
e.printStackTrace()
|
|
}
|
|
return 0
|
|
}
|
|
|
|
// Dependency Deobfuscation (Deprecated, use the new RFG API documented in dependencies.gradle)
|
|
|
|
def deobf(String sourceURL) {
|
|
try {
|
|
URL url = new URL(sourceURL)
|
|
String fileName = url.getFile()
|
|
|
|
//get rid of directories:
|
|
int lastSlash = fileName.lastIndexOf("/")
|
|
if (lastSlash > 0) {
|
|
fileName = fileName.substring(lastSlash + 1)
|
|
}
|
|
//get rid of extension:
|
|
if (fileName.endsWith(".jar") || fileName.endsWith(".litemod")) {
|
|
fileName = fileName.substring(0, fileName.lastIndexOf("."))
|
|
}
|
|
|
|
String hostName = url.getHost()
|
|
if (hostName.startsWith("www.")) {
|
|
hostName = hostName.substring(4)
|
|
}
|
|
List parts = Arrays.asList(hostName.split("\\."))
|
|
Collections.reverse(parts)
|
|
hostName = String.join(".", parts)
|
|
|
|
return deobf(sourceURL, "$hostName/$fileName")
|
|
} catch (Exception ignored) {
|
|
return deobf(sourceURL, "deobf/${sourceURL.hashCode()}")
|
|
}
|
|
}
|
|
|
|
def deobfMaven(String repoURL, String mavenDep) {
|
|
if (!repoURL.endsWith("/")) {
|
|
repoURL += "/"
|
|
}
|
|
String[] parts = mavenDep.split(":")
|
|
parts[0] = parts[0].replace('.', '/')
|
|
def jarURL = repoURL + parts[0] + "/" + parts[1] + "/" + parts[2] + "/" + parts[1] + "-" + parts[2] + ".jar"
|
|
return deobf(jarURL)
|
|
}
|
|
|
|
def deobfCurse(String curseDep) {
|
|
return dependencies.rfg.deobf("curse.maven:$curseDep")
|
|
}
|
|
|
|
// The method above is to be preferred. Use this method if the filename is not at the end of the URL.
|
|
def deobf(String sourceURL, String rawFileName) {
|
|
String bon2Version = "2.5.1"
|
|
String fileName = URLDecoder.decode(rawFileName, "UTF-8")
|
|
String cacheDir = "$project.gradle.gradleUserHomeDir/caches"
|
|
String obfFile = "$cacheDir/modules-2/files-2.1/${fileName}.jar"
|
|
|
|
download.run {
|
|
src sourceURL
|
|
dest obfFile
|
|
quiet true
|
|
overwrite false
|
|
}
|
|
return dependencies.rfg.deobf(files(obfFile))
|
|
}
|
|
// Helper methods
|
|
|
|
def checkPropertyExists(String propertyName) {
|
|
if (!project.hasProperty(propertyName)) {
|
|
throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/GTNewHorizons/ExampleMod1.7.10/blob/main/gradle.properties")
|
|
}
|
|
}
|
|
|
|
def propertyDefaultIfUnset(String propertyName, defaultValue) {
|
|
if (!project.hasProperty(propertyName) || project.property(propertyName) == "") {
|
|
project.ext.setProperty(propertyName, defaultValue)
|
|
}
|
|
}
|
|
|
|
def getFile(String relativePath) {
|
|
return new File(projectDir, relativePath)
|
|
}
|
|
|
|
def getSecondaryArtifacts() {
|
|
// Because noPublishedSources from the beginning of the script is somehow not visible here...
|
|
boolean noPublishedSources = project.hasProperty("noPublishedSources") ? project.noPublishedSources.toBoolean() : false
|
|
def secondaryArtifacts = [publishableDevJar]
|
|
if (!noPublishedSources) secondaryArtifacts += [sourcesJar]
|
|
if (apiPackage) secondaryArtifacts += [apiJar]
|
|
return secondaryArtifacts
|
|
}
|