From 485bb43a738aa7254b123ba32d78df156b4bf6bd Mon Sep 17 00:00:00 2001 From: tier940 Date: Thu, 1 Jun 2023 22:57:01 +0900 Subject: [PATCH 1/7] update new build --- addon.gradle | 6 + build.gradle | 1079 +++++++++++++++++++++++++++++++++++-------- dependencies.gradle | 66 +++ gradle.properties | 243 ++++++---- repositories.gradle | 27 ++ settings.gradle | 21 +- 6 files changed, 1148 insertions(+), 294 deletions(-) create mode 100644 addon.gradle create mode 100644 dependencies.gradle create mode 100644 repositories.gradle diff --git a/addon.gradle b/addon.gradle new file mode 100644 index 00000000..32bafca3 --- /dev/null +++ b/addon.gradle @@ -0,0 +1,6 @@ +gradleEnterprise { + buildScan { + termsOfServiceUrl = "https://gradle.com/terms-of-service" + termsOfServiceAgree = "yes" + } +} diff --git a/build.gradle b/build.gradle index baaf8b9d..22f33405 100644 --- a/build.gradle +++ b/build.gradle @@ -1,227 +1,558 @@ +//version: 1685514775 +/* + * 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/GregTechCEu/Buildscripts/blob/master/build.gradle for updates. + */ + +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import com.gtnewhorizons.retrofuturagradle.mcp.ReobfuscatedJar +import com.modrinth.minotaur.dependencies.ModDependency +import com.modrinth.minotaur.dependencies.VersionDependency +import org.gradle.api.tasks.testing.logging.TestExceptionFormat +import org.gradle.api.tasks.testing.logging.TestLogEvent +import org.gradle.internal.logging.text.StyledTextOutputFactory import org.jetbrains.gradle.ext.Gradle +import static org.gradle.internal.logging.text.StyledTextOutput.Style + plugins { - id('java') - id('java-library') - id('maven-publish') - id('idea') - id('org.jetbrains.gradle.plugin.idea-ext') version "$idea_ext_version" - id('com.gtnewhorizons.retrofuturagradle') version "$rfg_version" - //id('net.darkhax.curseforgegradle') version "$curseforge_gradle_version" apply false - //id('com.modrinth.minotaur') version "$minotaur_version" apply false + id 'java' + id 'java-library' + id 'eclipse' + id 'maven-publish' + id 'org.jetbrains.gradle.plugin.idea-ext' version '1.1.7' + id 'com.gtnewhorizons.retrofuturagradle' version '1.3.+' + id 'net.darkhax.curseforgegradle' version '1.0.+' apply false + id 'com.modrinth.minotaur' version '2.7.+' apply false + id 'com.diffplug.spotless' version '6.13.0' apply false + id 'com.palantir.git-version' version '3.0.0' apply false + id 'com.github.johnrengelman.shadow' version '8.1.1' apply false +} + +if (verifySettingsGradle()) { + throw new GradleException("Settings has been updated, please re-run task.") +} + +def out = services.get(StyledTextOutputFactory).create('an-output') + + +// Project properties + +// Required properties: we don't know how to handle these being missing gracefully +checkPropertyExists("modName") +checkPropertyExists("modId") +checkPropertyExists("modGroup") +checkPropertyExists("modVersion") +checkPropertyExists("minecraftVersion") // hard-coding this makes it harder to immediately tell what version a mod is in (even though this only really supports 1.12.2) +checkPropertyExists("apiPackage") +checkPropertyExists("accessTransformersFile") +checkPropertyExists("usesMixins") +checkPropertyExists("mixinsPackage") +checkPropertyExists("coreModClass") +checkPropertyExists("containsMixinsAndOrCoreModOnly") + +// Optional properties: we can assume some default behavior if these are missing +propertyDefaultIfUnset("autoUpdateBuildScript", false) +propertyDefaultIfUnset("modArchivesBaseName", project.modId) +propertyDefaultIfUnsetWithEnvVar("developmentEnvironmentUserName", "Developer", "DEV_USERNAME") +propertyDefaultIfUnset("generateGradleTokenClass", "") +propertyDefaultIfUnset("gradleTokenModId", "") +propertyDefaultIfUnset("gradleTokenModName", "") +propertyDefaultIfUnset("gradleTokenVersion", "") +propertyDefaultIfUnset("includeWellKnownRepositories", true) +propertyDefaultIfUnset("includeCommonDevEnvMods", true) +propertyDefaultIfUnset("noPublishedSources", false) +propertyDefaultIfUnset("forceEnableMixins", false) +propertyDefaultIfUnset("usesShadowedDependencies", false) +propertyDefaultIfUnset("minimizeShadowedDependencies", true) +propertyDefaultIfUnset("relocateShadowedDependencies", true) +propertyDefaultIfUnset("modrinthProjectId", "") +propertyDefaultIfUnset("modrinthRelations", "") +propertyDefaultIfUnset("curseForgeProjectId", "") +propertyDefaultIfUnset("curseForgeRelations", "") +propertyDefaultIfUnset("releaseType", "release") +propertyDefaultIfUnset("customMavenPublishUrl", "") +propertyDefaultIfUnset("enableModernJavaSyntax", false) +propertyDefaultIfUnset("enableSpotless", false) +propertyDefaultIfUnset("enableJUnit", false) +propertyDefaultIfUnsetWithEnvVar("deploymentDebug", false, "DEPLOYMENT_DEBUG") + + +// Project property assertions + +final String javaSourceDir = 'src/main/java/' +final String scalaSourceDir = 'src/main/scala/' +// If Kotlin is supported, add the path here + +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 +// If Kotlin is supported, add the path here + +if (!getFile(targetPackageJava).exists() && !getFile(targetPackageScala).exists()) { + throw new GradleException("Could not resolve \"modGroup\"! Could not find ${targetPackageJava} or ${targetPackageScala}") +} + +if (apiPackage) { + targetPackageJava = javaSourceDir + modGroupPath + '/' + apiPackagePath + targetPackageScala = scalaSourceDir + modGroupPath + '/' + apiPackagePath + if (!getFile(targetPackageJava).exists() && !getFile(targetPackageScala).exists()) { + throw new GradleException("Could not resolve \"apiPackage\"! Could not find ${targetPackageJava} or ${targetPackageScala}") + } +} + +if (accessTransformersFile) { + for (atFile in accessTransformersFile.split(",")) { + String targetFile = 'src/main/resources/' + 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) + } } -gradleEnterprise { - buildScan { - termsOfServiceUrl = "https://gradle.com/terms-of-service" - termsOfServiceAgree = "yes" +if (usesMixins.toBoolean()) { + if (mixinsPackage.isEmpty()) { + throw new GradleException("\"usesMixins\" requires \"mixinsPackage\" to be set!") + } + final String mixinPackagePath = mixinsPackage.toString().replaceAll('\\.', '/') + targetPackageJava = javaSourceDir + modGroupPath + '/' + mixinPackagePath + targetPackageScala = scalaSourceDir + modGroupPath + '/' + mixinPackagePath + if (!getFile(targetPackageJava).exists()) { + throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find ${targetPackageJava} or ${targetPackageScala}") } } -version = project.mod_version -group = project.maven_group -archivesBaseName = project.archives_base_name +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' + if (!getFile(targetFileJava).exists() && !getFile(targetFileScala).exists() && !getFile(targetFileScalaJava).exists()) { + throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava) + } +} + + +// Plugin application + +// Scala +if (getFile('src/main/scala').exists()) { + apply plugin: 'scala' +} + +// Spotless +//noinspection GroovyAssignabilityCheck +project.extensions.add(com.diffplug.blowdryer.Blowdryer, 'Blowdryer', com.diffplug.blowdryer.Blowdryer) // make Blowdryer available in plugin application +if (enableSpotless.toBoolean()) { + apply plugin: 'com.diffplug.spotless' + + // Spotless auto-formatter + // See https://github.com/diffplug/spotless/tree/main/plugin-gradle + // Can be locally toggled via spotless:off/spotless:on comments + spotless { + encoding 'UTF-8' + + format 'misc', { + target '.gitignore' + + trimTrailingWhitespace() + indentWithSpaces(4) + endWithNewline() + } + java { + target 'src/main/java/**/*.java', 'src/test/java/**/*.java' // exclude api as they are not our files + + def orderFile = project.file('spotless.importorder') + if (!orderFile.exists()) { + orderFile = Blowdryer.file('spotless.importorder') + } + def formatFile = project.file('spotless.eclipseformat.xml') + if (!formatFile.exists()) { + formatFile = Blowdryer.file('spotless.eclipseformat.xml') + } + + toggleOffOn() + importOrderFile(orderFile) + removeUnusedImports() + endWithNewline() + //noinspection GroovyAssignabilityCheck + eclipse('4.19.0').configFile(formatFile) + } + scala { + target 'src/*/scala/**/*.scala' + scalafmt('3.7.1') + } + } +} + +// Git submodules +if (project.file('.git/HEAD').isFile() || project.file('.git').isFile()) { + apply plugin: 'com.palantir.git-version' +} + +// Shadowing +if (usesShadowedDependencies.toBoolean()) { + apply plugin: 'com.github.johnrengelman.shadow' +} + + +// Configure Java -// Set the toolchain version to decouple the Java we run Gradle with from the Java used to compile and run the mod java { toolchain { - languageVersion.set(JavaLanguageVersion.of(project.java_version)) - // Azul covers the most platforms for Java 8 toolchains, crucially including MacOS arm64 + if (enableModernJavaSyntax.toBoolean()) { + languageVersion.set(JavaLanguageVersion.of(17)) + } else { + languageVersion.set(JavaLanguageVersion.of(8)) + } + // Azul covers the most platforms for Java 8+ toolchains, crucially including MacOS arm64 vendor.set(JvmVendorSpec.AZUL) } - // Generate sources and javadocs jars when building and publishing - withSourcesJar() - // javadoc jar throws errors on incomplete docs - // docs are also contained in the sources jar, so omit the javadoc-only jar - //withJavadocJar() + if (!noPublishedSources.toBoolean()) { + withSourcesJar() + } } tasks.withType(JavaCompile).configureEach { - options.encoding = "UTF-8" + options.encoding = 'UTF-8' + + if (enableModernJavaSyntax.toBoolean()) { + if (it.name in ['compileMcLauncherJava', 'compilePatchedMcJava']) { + return + } + + sourceCompatibility = 17 + options.release.set(8) + + javaCompiler.set(javaToolchains.compilerFor { + languageVersion.set(JavaLanguageVersion.of(17)) + vendor.set(JvmVendorSpec.AZUL) + }) + } } -configurations { - embed - implementation.extendsFrom(embed) +tasks.withType(ScalaCompile).configureEach { + options.encoding = 'UTF-8' } + +// Configure Minecraft + +version = modVersion +group = modGroup +archivesBaseName = modArchivesBaseName + minecraft { - mcVersion = '1.12.2' - def args = ["-ea:${project.group}"] - if (project.use_coremod.toBoolean()) { - args << '-Dfml.coreMods.load=' + project.coremod_plugin_class_name + mcVersion = minecraftVersion + username = developmentEnvironmentUserName.toString() + useDependencyAccessTransformers = true + + // Automatic token injection with RetroFuturaGradle + if (gradleTokenModId) { + injectedTags.put gradleTokenModId, modId + } + if (gradleTokenModName) { + injectedTags.put gradleTokenModName, modName } - if (project.use_mixins.toBoolean()) { - args << '-Dmixin.hotSwap=true' - args << '-Dmixin.checks.interfaces=true' - args << '-Dmixin.debug.export=true' + if (gradleTokenVersion) { + injectedTags.put gradleTokenVersion, modVersion } - extraRunJvmArguments.addAll(args) - useDependencyAccessTransformers = true + // JVM arguments + extraRunJvmArguments.add("-ea:${modGroup}") + if (usesMixins.toBoolean()) { + extraRunJvmArguments.addAll([ + '-Dmixin.hotSwap=true', + '-Dmixin.checks.interfaces=true', + '-Dmixin.debug.export=true' + ]) + } + if (coreModClass) { + extraRunJvmArguments.add("-Dfml.coreMods.load=${modGroup}.${coreModClass}") + } +} - injectedTags.put("VERSION", project.version) +if (generateGradleTokenClass) { + tasks.injectTags.outputClassName.set(generateGradleTokenClass) } -// Generate a my.project.Tags class with the version number as a field -tasks.injectTags.configure { - outputClassName.set("${project.group}.Tags") +tasks.named('processIdeaSettings').configure { + dependsOn('injectTags') } -repositories { - maven { // MixinBooter - name = 'Cleanroom Maven' - url = 'https://maven.cleanroommc.com' - } - maven { // Mixin - name = 'Sponge Maven' - url = 'https://repo.spongepowered.org/maven' - } - maven { // CurseForge - name = 'Curse Maven' - url = 'https://www.cursemaven.com' - content { - includeGroup 'curse.maven' + +// Allow others using this buildscript to have custom gradle code run +if (getFile('addon.gradle').exists()) { + apply from: 'addon.gradle' +} + + +// Repositories + +// Allow unsafe repos but warn +repositories.configureEach { repo -> + if (repo instanceof 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 } } - maven { // CraftTweaker and JEI Backup - name = 'BlameJared Maven' - url = 'https://maven.blamejared.com' +} + +// Allow adding custom repositories to the buildscript +if (getFile('repositories.gradle').exists()) { + apply from: 'repositories.gradle' +} + +repositories { + if (includeWellKnownRepositories.toBoolean() || includeCommonDevEnvMods.toBoolean()) { + exclusiveContent { + forRepository { + //noinspection ForeignDelegate + maven { + name = 'Curse Maven' + url = 'https://www.cursemaven.com' + } + } + filter { + includeGroup 'curse.maven' + } + } + exclusiveContent { + forRepository { + //noinspection ForeignDelegate + maven { + name = 'Modrinth' + url = 'https://api.modrinth.com/maven' + } + } + filter { + includeGroup 'maven.modrinth' + } + } + maven { + name 'Cleanroom Maven' + url 'https://maven.cleanroommc.com' + } + maven { + name 'BlameJared Maven' + url 'https://maven.blamejared.com' + } } - maven { // Autoconfig and Autosave - name = 'Mod Maven' - url = 'https://modmaven.dev' + if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { + maven { + name 'Sponge Maven' + url 'https://repo.spongepowered.org/maven' + } + // need to add this here even if we did not above + if (!includeWellKnownRepositories.toBoolean()) { + maven { + name 'Cleanroom Maven' + url 'https://maven.cleanroommc.com' + } + } } mavenLocal() // Must be last for caching to work } + +// Dependencies + +// Configure dependency configurations +configurations { + embed + implementation.extendsFrom(embed) + + if (usesShadowedDependencies.toBoolean()) { + for (config in [compileClasspath, runtimeClasspath, testCompileClasspath, testRuntimeClasspath]) { + config.extendsFrom(shadowImplementation) + config.extendsFrom(shadowCompile) + } + } +} + dependencies { - // Hard Dependencies - // the CCL deobf jar uses very old MCP mappings, making it error at runtime in runClient/runServer - // therefore we manually deobf the regular jar - implementation rfg.deobf("curse.maven:codechicken-lib-1-8-${ccl_pid}:${ccl_fid}") - implementation rfg.deobf("curse.maven:gregtech-ce-unofficial-${ceu_pid}:${ceu_fid}") - //implementation (files("libs/gregtech-1.12.2-2.6.1-beta-deobf.jar")) - implementation rfg.deobf("curse.maven:gregicality-multiblocks-${gcm_pid}:${gcm_fid}") - implementation rfg.deobf("curse.maven:ae2-extended-life-${ae2_pid}:${ae2_fid}") - implementation rfg.deobf("curse.maven:enderio-${eio_pid}:${eio_fid}") - implementation rfg.deobf("curse.maven:ender-io-conduits-${eic_pid}:${eic_fid}") - implementation rfg.deobf("curse.maven:endercore-${eco_pid}:${eco_fid}") - implementation "info.loenwind.autoconfig:AutoConfig:${minecraft_version}-${autoconfig_version}" - implementation "info.loenwind.autosave:AutoSave:${minecraft_version}-${autosave_version}" - implementation rfg.deobf("curse.maven:baubles-${bal_pid}:${bal_fid}") - implementation rfg.deobf("curse.maven:shadowfacts-forgelin-${sff_pid}:${sff_fid}") - implementation rfg.deobf("curse.maven:ae-additions-extra-cells-2-fork-${aea_pid}:${aea_fid}") - - // Soft Dependencies - compileOnlyApi rfg.deobf("curse.maven:gregtech-food-option-${gfo_pid}:${gfo_fid}") - implementation "mezz.jei:jei_1.12.2:${jei_version}" - implementation "CraftTweaker2:CraftTweaker2-MC1120-Main:1.12-${crt_version}" - implementation rfg.deobf("curse.maven:top-${top_pid}:${top_fid}") - implementation rfg.deobf("curse.maven:ctm-${ctm_pid}:${ctm_fid}") - - // use a local jar for GroovyScript to avoid a bug from Mixin and ForgeGradle, - // causing crashes at run-time when deobfuscated - implementation files("libs/groovyscript-0.4.0.jar") - //implementation rfg.deobf("curse.maven:groovyscript-${grs_pid}:${grs_fid}") - - // Debug Draconic Evolution/Additions - compileOnlyApi rfg.deobf("curse.maven:redstone-flux-${ref_pid}:${ref_fid}") - compileOnlyApi rfg.deobf("curse.maven:brandons-core-${brc_pid}:${brc_fid}") - compileOnlyApi rfg.deobf("curse.maven:draconic-evolution-${dre_pid}:${dre_fid}") - compileOnlyApi rfg.deobf("curse.maven:draconicadditions-${dra_pid}:${dra_fid}") - if (project.debug_de.toBoolean()) { - implementation rfg.deobf("curse.maven:redstone-flux-${ref_pid}:${ref_fid}") - implementation rfg.deobf("curse.maven:brandons-core-${brc_pid}:${brc_fid}") - implementation rfg.deobf("curse.maven:draconic-evolution-${dre_pid}:${dre_fid}") - implementation rfg.deobf("curse.maven:draconicadditions-${dra_pid}:${dra_fid}") - } - - // GroovyScript dependency - implementation "zone.rong:mixinbooter:${mixinbooter_version}" - - // Mixin dependencies - api("org.spongepowered:mixin:${mixin_version}") { transitive = false } - annotationProcessor("org.spongepowered:mixin:${mixin_version}") { transitive = false } - - annotationProcessor("org.ow2.asm:asm-debug-all:${asm_debug_version}") - annotationProcessor("com.google.guava:guava:${guava_version}-jre") - annotationProcessor("com.google.code.gson:gson:${gson_version}") - - // Boot error fix - runtimeOnly (files("libs/EnderCore-1.12.2-0.5.76-core.jar")) -} - -def mixinConfigRefMap = 'mixins.' + project.maven_group + '.refmap.json' -def mixinTmpDir = buildDir.path + File.separator + 'tmp' + File.separator + 'mixins' -def refMap = "${mixinTmpDir}" + File.separator + mixinConfigRefMap -def mixinSrg = "${mixinTmpDir}" + File.separator + "mixins.srg" - -if (project.use_mixins.toBoolean()) { - tasks.named("reobfJar", ReobfuscatedJar).configure { - extraSrgFiles.from(mixinSrg) - } - - tasks.named("compileJava", JavaCompile).configure { - doFirst { - new File(mixinTmpDir).mkdirs() - } - options.compilerArgs += [ - "-AreobfSrgFile=${tasks.reobfJar.srg.get().asFile}", - "-AoutSrgFile=${mixinSrg}", - "-AoutRefMapFile=${refMap}", - ] + if (usesMixins.toBoolean() || forceEnableMixins.toBoolean()) { + implementation 'zone.rong:mixinbooter:7.0' + api('org.spongepowered:mixin:0.8.3') { + transitive = false + } + annotationProcessor('org.spongepowered:mixin:0.8.3') { + transitive = false + } + + annotationProcessor 'org.ow2.asm:asm-debug-all:5.2' + // should use 24.1.1 but 30.0+ has a vulnerability fix + annotationProcessor 'com.google.guava:guava:30.0-jre' + // should use 2.8.6 but 2.8.9+ has a vulnerability fix + annotationProcessor 'com.google.code.gson:gson:2.8.9' + } + + if (enableJUnit.toBoolean()) { + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1' + testImplementation 'org.hamcrest:hamcrest:2.2' + } + + if (enableModernJavaSyntax.toBoolean()) { + annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:1.0.0' + compileOnly('com.github.bsideup.jabel:jabel-javac-plugin:1.0.0') { + transitive = false + } + // workaround for https://github.com/bsideup/jabel/issues/174 + annotationProcessor 'net.java.dev.jna:jna-platform:5.13.0' + // Allow jdk.unsupported classes like sun.misc.Unsafe, workaround for JDK-8206937 and fixes Forge crashes in tests. + patchedMinecraft 'me.eigenraven.java8unsupported:java-8-unsupported-shim:1.0.0' + + // allow Jabel to work in tests + testAnnotationProcessor "com.github.bsideup.jabel:jabel-javac-plugin:1.0.0" + testCompileOnly("com.github.bsideup.jabel:jabel-javac-plugin:1.0.0") { + transitive = false // We only care about the 1 annotation class + } + testCompileOnly "me.eigenraven.java8unsupported:java-8-unsupported-shim:1.0.0" + } + + compileOnlyApi 'org.jetbrains:annotations:23.0.0' + annotationProcessor 'org.jetbrains:annotations:23.0.0' + + if (includeCommonDevEnvMods.toBoolean()) { + implementation 'mezz.jei:jei_1.12.2:4.16.1.302' + //noinspection DependencyNotationArgument + implementation rfg.deobf('curse.maven:top-245211:2667280') // TOP 1.4.28 } } -if (project.use_access_transformer.toBoolean()) { - for (File at : sourceSets.getByName("main").resources.files) { - if (at.name.toLowerCase().endsWith("_at.cfg")) { - tasks.deobfuscateMergedJarToSrg.accessTransformerFiles.from(at) - tasks.srgifyBinpatchedJar.accessTransformerFiles.from(at) +if (getFile('dependencies.gradle').exists()) { + apply from: 'dependencies.gradle' +} + + +// Test configuration + +// Ensure tests have access to minecraft classes +sourceSets { + test { + java { + compileClasspath += patchedMc.output + mcLauncher.output + runtimeClasspath += patchedMc.output + mcLauncher.output } } } +test { + // ensure tests are run with java8 + javaLauncher = javaToolchains.launcherFor { + languageVersion = JavaLanguageVersion.of(8) + }.get() + + testLogging { + events TestLogEvent.STARTED, TestLogEvent.PASSED, TestLogEvent.FAILED + exceptionFormat TestExceptionFormat.FULL + showExceptions true + showStackTraces true + showCauses true + showStandardStreams true + } + + if (enableJUnit.toBoolean()) { + useJUnitPlatform() + } +} + + +// Resource processing and jar building + processResources { // this will ensure that this task is redone when the versions change. - inputs.property 'version', project.version - inputs.property 'mcversion', project.minecraft_version + inputs.property 'version', modVersion + inputs.property 'mcversion', minecraftVersion + // Blowdryer puts these files into the resource directory, so + // exclude them from builds (doesn't hurt to exclude even if not present) + exclude('spotless.importorder') + exclude('spotless.eclipseformat.xml') + // replace stuff in mcmod.info, nothing else - filesMatching(['mcmod.info', 'pack.mcmeta']) { fcd -> - // replace version and mcversion - fcd.expand ( - 'version': project.version, - 'mcversion': project.minecraft_version + filesMatching('mcmod.info') { fcd -> + fcd.expand( + 'version': modVersion, + 'mcversion': minecraftVersion, + 'modid': modId, + 'modname': modName ) } +} + +// Automatically generate a mixin json file if it does not already exist +tasks.register('generateAssets') { + group = 'GT Buildscript' + description = 'Generates a pack.mcmeta, mcmod.info, or mixins.{modid}.json if needed' + doLast { + // pack.mcmeta + def packMcmetaFile = getFile('src/main/resources/pack.mcmeta') + if (!packMcmetaFile.exists()) { + packMcmetaFile.text = """{ + "pack": { + "pack_format": 3, + "description": "${modName} Resource Pack" + } +} +""" + } - if (project.use_access_transformer.toBoolean()) { - rename '(.+_at.cfg)', 'META-INF/$1' // Access Transformers + // mcmod.info + def mcmodInfoFile = getFile('src/main/resources/mcmod.info') + if (!mcmodInfoFile.exists()) { + mcmodInfoFile.text = """[{ + "modid": "\${modid}", + "name": "\${modname}", + "description": "An example mod for Minecraft 1.12.2 with Forge", + "version": "\${version}", + "mcversion": "\${mcversion}", + "logoFile": "", + "url": "", + "authorList": [], + "credits": "", + "dependencies": [] +}] +""" + mcmodInfoFile + } + + // mixins.{modid}.json + if (usesMixins.toBoolean()) { + def mixinConfigFile = getFile("src/main/resources/mixins.${modId}.json") + if (!mixinConfigFile.exists()) { + def mixinConfigRefmap = "mixins.${modId}.refmap.json" + + mixinConfigFile.text = """{ + "package": "${modGroup}.${mixinsPackage}", + "refmap": "${mixinConfigRefmap}", + "target": "@env(DEFAULT)", + "minVersion": "0.8", + "compatibilityLevel": "JAVA_8", + "mixins": [], + "client": [], + "server": [] +} +""" + } + } } +} - if (project.use_mixins.toBoolean()) { - // Embed mixin refmap - from refMap - dependsOn("compileJava") +if (usesMixins.toBoolean()) { + tasks.named('processResources').configure { + dependsOn('generateAssets') } } jar { manifest { - def attribute_map = [:] - if (use_coremod.toBoolean()) { - attribute_map['FMLCorePlugin'] = project.coremod_plugin_class_name - if (include_mod.toBoolean()) { - attribute_map['FMLCorePluginContainsFMLMod'] = true - attribute_map['ForceLoadAsMod'] = project.gradle.startParameter.taskNames[0] == "build" - } - } - if (use_access_transformer.toBoolean()) { - attribute_map['FMLAT'] = project.maven_group + '_at.cfg' - } - attributes(attribute_map) + attributes(getManifestAttributes()) } // Add all embedded dependencies into the jar @@ -232,33 +563,128 @@ jar { } } +// Create API library jar +tasks.register('apiJar', Jar) { + archiveClassifier.set 'api' + from(sourceSets.main.java) { + include "${modGroupPath}/${apiPackagePath}/**" + } + + from(sourceSets.main.output) { + include "${modGroupPath}/${apiPackagePath}/**" + } +} + +// Configure shadow jar task +if (usesShadowedDependencies.toBoolean()) { + tasks.named('shadowJar', ShadowJar).configure { + manifest { + attributes(getManifestAttributes()) + } + // Only shadow classes that are actually used, if enabled + if (minimizeShadowedDependencies.toBoolean()) { + minimize() + } + configurations = [ + project.configurations.shadowImplementation, + project.configurations.shadowCompile + ] + 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']) { + tasks.named(runTask).configure { + dependsOn('shadowJar') + } + } +} + +def getManifestAttributes() { + def attributes = [:] + if (coreModClass) { + attributes['FMLCorePlugin'] = "${modGroup}.${coreModClass}" + } + if (!containsMixinsAndOrCoreModOnly.toBoolean() && (usesMixins.toBoolean() || coreModClass)) { + attributes['FMLCorePluginContainsFMLMod'] = true + } + if (accessTransformersFile) { + attributes['FMLAT'] = accessTransformersFile.toString() + } + + if (usesMixins.toBoolean()) { + attributes['ForceLoadAsMod'] = !containsMixinsAndOrCoreModOnly.toBoolean() + } + return attributes +} + + +// IDE Configuration + +eclipse { + classpath { + downloadSources = true + downloadJavadoc = true + } +} + idea { module { - inheritOutputDirs = true - downloadJavadoc = true - downloadSources = true + inheritOutputDirs true + downloadJavadoc true + downloadSources true } project { settings { runConfigurations { - "1. Run Client"(Gradle) { - taskNames = ["runClient"] + '1. Run Client'(Gradle) { + taskNames = ['runClient'] } - "2. Run Server"(Gradle) { - taskNames = ["runServer"] + '2. Run Server'(Gradle) { + taskNames = ['runServer'] } - "3. Run Obfuscated Client"(Gradle) { - taskNames = ["runObfClient"] + '3. Run Obfuscated Client'(Gradle) { + taskNames = ['runObfClient'] } - "4. Run Obfuscated Server"(Gradle) { - taskNames = ["runObfServer"] + '4. Run Obfuscated Server'(Gradle) { + taskNames = ['runObfServer'] + } + if (enableSpotless.toBoolean()) { + "5. Apply Spotless"(Gradle) { + taskNames = ["spotlessApply"] + } + } + 'Update Buildscript'(Gradle) { + taskNames = ['updateBuildScript'] + } + 'FAQ'(Gradle) { + taskNames = ['faq'] } } compiler.javac { afterEvaluate { - javacAdditionalOptions = "-encoding utf8" + javacAdditionalOptions = '-encoding utf8' moduleJavacAdditionalOptions = [ - (project.name + ".main"): tasks.compileJava.options.compilerArgs.collect { '"' + it + '"' }.join(' ') + (project.name + '.main'): tasks.compileJava.options.compilerArgs.collect { + '"' + it + '"' + }.join(' ') ] } } @@ -266,27 +692,294 @@ idea { } } -// Create API library jar -tasks.register('apiJar', Jar) { - archiveClassifier.set 'api' - from(sourceSets.main.java) { - include maven_group + '/api/**' + +// Deployment + +final boolean isCIEnv = providers.environmentVariable('CI').getOrElse('false').toBoolean() +def final changelogEnv = providers.environmentVariable('CHANGELOG_LOCATION') +File changelogFile = new File(changelogEnv.getOrElse('CHANGELOG.md')) + +if (isCIEnv || deploymentDebug.toBoolean()) { + artifacts { + if (!noPublishedSources.toBoolean()) { + archives sourcesJar + } + if (apiPackage) { + archives apiJar + } } +} - from(sourceSets.main.output) { - include maven_group + '/api/**' +// Curseforge +def final cfApiKey = providers.environmentVariable('CURSEFORGE_API_KEY') +if (cfApiKey.isPresent() || deploymentDebug.toBoolean()) { + apply plugin: 'net.darkhax.curseforgegradle' + //noinspection UnnecessaryQualifiedReference + tasks.register('curseforge', net.darkhax.curseforgegradle.TaskPublishCurseForge) { + apiToken = cfApiKey.get() + def projectIdVar = providers.environmentVariable('CURSEFORGE_PROJECT_ID') + + def mainFile = upload(projectIdVar.getOrElse(curseForgeProjectId), reobfJar) + def changelogRaw = changelogFile.exists() ? changelogFile.getText('UTF-8') : "" + + mainFile.releaseType = getReleaseType() + mainFile.changelog = changelogRaw + mainFile.changelogType = 'markdown' + mainFile.addModLoader 'Forge' + mainFile.addJavaVersion "Java 8" + mainFile.addGameVersion minecraftVersion + + if (curseForgeRelations.size() != 0) { + String[] deps = curseForgeRelations.split(';') + deps.each { dep -> + if (dep.size() == 0) { + return + } + String parts = dep.split(':') + String type = parts[0], slug = parts[1] + if(!(type in ['requiredDependency', 'embeddedLibrary', 'optionalDependency', 'tool', 'incompatible'])) { + throw new Exception('Invalid Curseforge dependency type: ' + type) + } + mainFile.addRelation(slug, type) + } + } + + for (artifact in getSecondaryArtifacts()) { + def additionalFile = mainFile.withAdditionalFile(artifact) + additionalFile.changelog = changelogRaw + } + disableVersionDetection() + debugMode = deploymentDebug.toBoolean() } + tasks.curseforge.dependsOn(build) } -sourceSets { - test { - java { - compileClasspath += patchedMc.output + mcLauncher.output - runtimeClasspath += patchedMc.output + mcLauncher.output +// Modrinth +def final modrinthApiKey = providers.environmentVariable('MODRINTH_API_KEY') +if (modrinthApiKey.isPresent() || deploymentDebug.toBoolean()) { + apply plugin: 'com.modrinth.minotaur' + def final projectIdVar = providers.environmentVariable('MODRINTH_PROJECT_ID') + + modrinth { + token = modrinthApiKey.get() + projectId = projectIdVar.getOrElse(modrinthProjectId) + changelog = changelogFile.exists() ? changelogFile.getText('UTF-8') : "" + versionType = getReleaseType() + versionNumber = modVersion + gameVersions = [minecraftVersion] + loaders = ["forge"] + debugMode = deploymentDebug.toBoolean() + uploadFile = reobfJar + additionalFiles = getSecondaryArtifacts() + } + 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]) + } + } + tasks.modrinth.dependsOn(build) +} + +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) +} + +if (customMavenPublishUrl) { + String publishedVersion = modVersion + + publishing { + publications { + create('maven', MavenPublication) { + //noinspection GroovyAssignabilityCheck + from components.java + + if (apiPackage) { + artifact apiJar + } + + // providers is not available here, use System for getting env vars + groupId = System.getenv('ARTIFACT_GROUP_ID') ?: project.group + artifactId = System.getenv('ARTIFACT_ID') ?: project.name + version = System.getenv('RELEASE_VERSION') ?: publishedVersion + } + } + + repositories { + maven { + url = customMavenPublishUrl + allowInsecureProtocol = !customMavenPublishUrl.startsWith('https') + credentials { + username = providers.environmentVariable('MAVEN_USER').getOrElse('NONE') + password = providers.environmentVariable('MAVEN_PASSWORD').getOrElse('NONE') + } + } + } + } +} + + +// Buildscript updating + +def buildscriptGradleVersion = '8.1.1' + +tasks.named('wrapper', Wrapper).configure { + gradleVersion = buildscriptGradleVersion +} + +tasks.register('updateBuildScript') { + group = 'GT 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") + } + } +} + +static URL availableBuildScriptUrl() { + new URL("https://raw.githubusercontent.com/GregTechCEu/Buildscripts/master/build.gradle") +} + +static URL exampleSettingsGradleUrl() { + new URL("https://raw.githubusercontent.com/GregTechCEu/Buildscripts/master/settings.gradle") +} + +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!") + if (verifySettingsGradle()) { + throw new GradleException("Settings has been updated, please re-run task.") } + return true + } + return false +} + +boolean isNewBuildScriptVersionAvailable() { + Map parameters = ["connectTimeout": 10000, "readTimeout": 10000] + + 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 "" +} + + +// Faq + +tasks.register('faq') { + group = 'GT Buildscript' + description = 'Prints frequently asked questions about building a project' + doLast { + print("\nTo update this buildscript to the latest version, run 'gradlew updateBuildScript' or run the generated run configuration if you are using IDEA.\n" + + "To set up the project, run the 'setupDecompWorkspace' task, which you can run as './gradlew setupDecompWorkspace' in a terminal, or find in the 'modded minecraft' gradle category.\n\n" + + "To add new dependencies to your project, place them in 'dependencies.gradle', NOT in 'build.gradle' as they would be replaced when the script updates.\n" + + "To add new repositories to your project, place them in 'repositories.gradle'.\n" + + "If you need additional gradle code to run, you can place it in a file named 'addon.gradle' (or either of the above, up to you for organization).\n\n" + + "If your build fails to recognize the syntax of newer Java versions, enable Jabel in your 'gradle.properties' under the option name 'enableModernJavaSyntax'.\n" + + "To see information on how to configure your IDE properly for Java 17, see https://github.com/GregTechCEu/Buildscripts/blob/master/jabel.md\n\n" + + "Report any issues or feature requests you have for this build script to https://github.com/GregTechCEu/Buildscripts/issues\n") } } -tasks.named("processIdeaSettings").configure { - dependsOn("injectTags") + +// Helpers + +def getFile(String relativePath) { + return new File(projectDir, relativePath) +} + +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/GregTechCEu/Buildscripts/blob/main/gradle.properties") + } +} + +def propertyDefaultIfUnset(String propertyName, defaultValue) { + if (!project.hasProperty(propertyName) || project.property(propertyName) == "") { + project.ext.setProperty(propertyName, defaultValue) + } +} + +def propertyDefaultIfUnsetWithEnvVar(String propertyName, defaultValue, String envVarName) { + def envVar = providers.environmentVariable(envVarName) + if (envVar.isPresent()) { + project.ext.setProperty(propertyName, envVar.get()) + } else { + propertyDefaultIfUnset(propertyName, defaultValue) + } +} + +def getSecondaryArtifacts() { + def secondaryArtifacts = [usesShadowedDependencies.toBoolean() ? tasks.shadowJar : tasks.jar] + if (!noPublishedSources.toBoolean()) secondaryArtifacts += [sourcesJar] + if (apiPackage) secondaryArtifacts += [apiJar] + return secondaryArtifacts +} + +def getReleaseType() { + String type = releaseType + if (!(type in ['release', 'beta', 'alpha'])) { + throw new Exception("Release type invalid! Found \"" + type + "\", allowed: \"release\", \"beta\", \"alpha\"") + } + return type } diff --git a/dependencies.gradle b/dependencies.gradle new file mode 100644 index 00000000..38f95dd8 --- /dev/null +++ b/dependencies.gradle @@ -0,0 +1,66 @@ +//file:noinspection DependencyNotationArgument +// TODO remove when fixed in RFG ^ +/* + * Add your dependencies here. Common configurations: + * - implementation("group:name:version:classifier"): if you need this for internal implementation details of the mod. + * Available at compiletime and runtime for your environment. + * + * - compileOnlyApi("g:n:v:c"): if you need this for internal implementation details of the mod. + * Available at compiletime but not runtime for your environment. + * + * - annotationProcessor("g:n:v:c"): mostly for java compiler plugins, if you know you need this, use it, otherwise don't worry + * + * - testCONFIG("g:n:v:c"): replace CONFIG by one of the above, same as above but for the test sources instead of main + * + * You can exclude transitive dependencies (dependencies of the chosen dependency) by appending { transitive = false } if needed. + * + * To add a mod with CurseMaven, replace '("g:n:v:c")' in the above with 'rfg.deobf("curse.maven:project_slug-project_id:file_id")' + * Example: implementation rfg.deobf("curse.maven:gregtech-ce-unofficial-557242:4527757") + * + * For more details, see https://docs.gradle.org/8.0.1/userguide/java_library_plugin.html#sec:java_library_configurations_graph + */ +dependencies { + // Hard Dependencies + // the CCL deobf jar uses very old MCP mappings, making it error at runtime in runClient/runServer + // therefore we manually deobf the regular jar + implementation rfg.deobf("curse.maven:codechicken-lib-1-8-242818:2779848") + implementation rfg.deobf("curse.maven:gregtech-ce-unofficial-557242:4527757") + //implementation (files("libs/gregtech-1.12.2-2.6.1-beta-deobf.jar")) + implementation rfg.deobf("curse.maven:gregicality-multiblocks-564858:4529101") + implementation rfg.deobf("curse.maven:ae2-extended-life-570458:4505114") + implementation rfg.deobf("curse.maven:enderio-64578:3328811") + implementation rfg.deobf("curse.maven:ender-io-conduits-304346:3328808") + implementation rfg.deobf("curse.maven:endercore-231868:2972849") + implementation "info.loenwind.autoconfig:AutoConfig:1.12.2-1.0.2" + implementation "info.loenwind.autosave:AutoSave:1.12.2-1.0.11" + implementation rfg.deobf("curse.maven:baubles-227083:2518667") + implementation rfg.deobf("curse.maven:shadowfacts-forgelin-248453:2785465") + implementation rfg.deobf("curse.maven:ae-additions-extra-cells-2-fork-493962:3814371") + + // Soft Dependencies + compileOnlyApi rfg.deobf("curse.maven:gregtech-food-option-477021:4555292") + implementation "mezz.jei:jei_1.12.2:4.16.1.302" + implementation "CraftTweaker2:CraftTweaker2-MC1120-Main:1.12-4.1.20.687" + implementation rfg.deobf("curse.maven:top-245211:2667280") + implementation rfg.deobf("curse.maven:ctm-267602:2915363") + + // use a local jar for GroovyScript to avoid a bug from Mixin and ForgeGradle, + // causing crashes at run-time when deobfuscated + implementation files("libs/groovyscript-0.4.0.jar") + //implementation rfg.deobf("curse.maven:groovyscript-687577:4399621") + + // Debug Draconic Evolution/Additions + compileOnlyApi rfg.deobf("curse.maven:redstone-flux-270789:2920436") + compileOnlyApi rfg.deobf("curse.maven:brandons-core-231382:3408276") + compileOnlyApi rfg.deobf("curse.maven:draconic-evolution-223565:3431261") + compileOnlyApi rfg.deobf("curse.maven:draconicadditions-314515:3514704") + if (project.debug_de.toBoolean()) { + implementation rfg.deobf("curse.maven:redstone-flux-270789:2920436") + implementation rfg.deobf("curse.maven:brandons-core-231382:3408276") + implementation rfg.deobf("curse.maven:draconic-evolution-223565:3431261") + implementation rfg.deobf("curse.maven:draconicadditions-314515:3514704") + } + + // Boot error fix + runtimeOnly (files("libs/EnderCore-1.12.2-0.5.76-core.jar")) +} diff --git a/gradle.properties b/gradle.properties index 6fd4a94a..76e664b1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,101 +1,154 @@ +modName = GTExportCore + +# This is a case-sensitive string to identify your mod. Convention is to use lower case. +modId = gtexpert + +modGroup = gtexpert + +modVersion = 1.3.15-beta + +# The name of your jar when you produce builds, not including any versioning info +modArchivesBaseName = GTExportCore + +# Will update your build.gradle automatically whenever an update is available +autoUpdateBuildScript = true + +minecraftVersion = 1.12.2 + +# Debug mod compatibility +debug_de = false + +# Select a username for testing your mod with breakpoints. You may leave this empty for a random username each time you +# restart Minecraft in development. Choose this dependent on your mod: +# Do you need consistent player progressing (for example Thaumcraft)? -> Select a name +# Do you need to test how your custom blocks interacts with a player that is not the owner? -> leave name empty +# Alternatively this can be set with the 'DEV_USERNAME' environment variable. +developmentEnvironmentUserName = Developer + +# Enables using modern java syntax (up to version 17) via Jabel, while still targeting JVM 8. +# See https://github.com/bsideup/jabel for details on how this works. +# Using this requires that you use a Java 17 JDK for development. +enableModernJavaSyntax = true + +# Generate a class with String fields for the mod id, name and version named with the fields below +generateGradleTokenClass = gtexpert.Tags +gradleTokenModId = +gradleTokenModName = +gradleTokenVersion = VERSION + +# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise, you can +# leave this property empty. +# Example value: apiPackage = api + modGroup = com.myname.mymodid -> com.myname.mymodid.api +apiPackage = + +# Specify the configuration file for Forge's access transformers here. It must be placed into /src/main/resources/ +# There can be multiple files in a comma-separated list. +# Example value: mymodid_at.cfg,jei_at.cfg +accessTransformersFile = + +# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled! +usesMixins = false +# Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail! +mixinsPackage = +# Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin! +# Example value: coreModClass = asm.FMLPlugin + modGroup = com.myname.mymodid -> com.myname.mymodid.asm.FMLPlugin +coreModClass = GTEMixinPlugin +# If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod (meaning that +# there is no class annotated with @Mod) you want this to be true. When in doubt: leave it on false! +containsMixinsAndOrCoreModOnly = false + +# Enables Mixins even if this mod doesn't use them, useful if one of the dependencies uses mixins. +forceEnableMixins = true + +# Adds CurseMaven, Modrinth Maven, BlameJared maven, and some more well-known 1.12.2 repositories +includeWellKnownRepositories = true + +# Adds JEI and TheOneProbe to your development environment. Adds them as 'implementation', meaning they will +# be available at compiletime and runtime for your mod (in-game and in-code). +# Overrides the above setting to be always true, as these repositories are needed to fetch the mods +includeCommonDevEnvMods = true + + +# If enabled, you may use 'shadowCompile' for dependencies. They will be integrated in your jar. It is your +# responsibility check the licence and request permission for distribution, if required. +usesShadowedDependencies = false +# If disabled, won't remove unused classes from shaded dependencies. Some libraries use reflection to access +# their own classes, making the minimization unreliable. +minimizeShadowedDependencies = true +# If disabled, won't rename the shadowed classes. +relocateShadowedDependencies = true + + +# Publishing to modrinth requires you to set the MODRINTH_API_KEY environment variable to your current modrinth API token. + +# The project's ID on Modrinth. Can be either the slug or the ID. +# Leave this empty if you don't want to publish on Modrinth. +# Alternatively this can be set with the 'MODRINTH_PROJECT_ID' environment variable. +modrinthProjectId = + +# The project's relations on Modrinth. You can use this to refer to other projects on Modrinth. +# Syntax: scope1-type1:name1;scope2-type2:name2;... +# Where scope can be one of [required, optional, incompatible, embedded], +# type can be one of [project, version], +# and the name is the Modrinth project or version slug/id of the other mod. +# Example: required-project:jei;optional-project:top;incompatible-project:gregtech +modrinthRelations = + + +# Publishing to CurseForge requires you to set the CURSEFORGE_API_KEY environment variable to one of your CurseForge API tokens. + +# The project's numeric ID on CurseForge. You can find this in the About Project box. +# Leave this empty if you don't want to publish on CurseForge. +# Alternatively this can be set with the 'CURSEFORGE_PROJECT_ID' environment variable. +curseForgeProjectId = 851103 + +# The project's relations on CurseForge. You can use this to refer to other projects on CurseForge. +# Syntax: type1:name1;type2:name2;... +# Where type can be one of [requiredDependency, embeddedLibrary, optionalDependency, tool, incompatible], +# and the name is the CurseForge project slug of the other mod. +# Example: requiredDependency:railcraft;embeddedLibrary:cofhlib;incompatible:buildcraft +curseForgeRelations = + +# This project's release type on CurseForge and/or Modrinth +# Allowed types: release, beta, alpha +releaseType = beta + +# Prevent the source code from being published +noPublishedSources = false + + +# Publish to a custom maven location. Follows a few rules: +# Group ID can be set with the 'ARTIFACT_GROUP_ID' environment variable, default to 'project.group' +# Artifact ID can be set with the 'ARTIFACT_ID' environment variable, default to 'project.name' +# Version can be set with the 'RELEASE_VERSION' environment variable, default to 'modVersion' +# For maven credentials: +# Username is set with the 'MAVEN_USER' environment variable, default to "NONE" +# Password is set with the 'MAVEN_PASSWORD' environment variable, default to "NONE" +customMavenPublishUrl = + +# Enable spotless checks +# Enforces code formatting on your source code +# By default this will use the files found here: https://github.com/GregTechCEu/Buildscripts/tree/master/spotless +# to format your code. However, you can create your own version of these files and place them in your project's +# root directory to apply your own formatting options instead. +enableSpotless = false + +# Enable JUnit testing platform used for testing your code. +# Uses JUnit 5. See guide and documentation here: https://junit.org/junit5/docs/current/user-guide/ +enableJUnit = true + +# Deployment debug setting +# Uncomment this to test deployments to CurseForge and Modrinth +# Alternatively, you can set the 'DEPLOYMENT_DEBUG' environment variable. +deploymentDebug = false + + +# Gradle Settings +# Effectively applies the '--stacktrace' flag by default +org.gradle.logging.stacktrace = all # Sets default memory used for gradle commands. Can be overridden by user or command line properties. # This is required to provide enough memory for the Minecraft decompilation process. org.gradle.daemon = true org.gradle.parallel = true org.gradle.caching = true org.gradle.jvmargs = -Xmx3G -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -Dfile.encoding=UTF-8 - -# Mod Information -minecraft_version = 1.12.2 -mod_version = 1.3.15 -maven_group = gtexpert -archives_base_name = GTExportCore - -# If any properties changes below this line, run `gradlew setupDecompWorkspace` and refresh gradle again to ensure everything is working correctly. - -# Boilerplate Options -# mixins are enabled for GroovyScript to work in dev -use_mixins = false -use_coremod = false -use_assetmover = false - -# Access Transformer files should be in the root of `resources` folder and with the filename formatted as: `{archives_base_name}_at.cfg` -use_access_transformer = false - -# Coremod Arguments -include_mod = false -coremod_plugin_class_name = gtexpert.GTEMixinPlugin - -## Hard Dependencies -ccl_pid = 242818 -ccl_fid = 2779848 -ceu_pid = 557242 -ceu_fid = 4527757 -gcm_pid = 564858 -gcm_fid = 4529101 -ae2_pid = 570458 -ae2_fid = 4505114 -eio_pid = 64578 -eio_fid = 3328811 -eic_pid = 304346 -eic_fid = 3328808 -eco_pid = 231868 -eco_fid = 2972849 -autoconfig_version = 1.0.2 -autosave_version = 1.0.11 -bal_pid = 227083 -bal_fid = 2518667 -sff_pid = 248453 -sff_fid = 2785465 -aea_pid = 493962 -aea_fid = 3814371 - -## Soft Dependencies -gfo_pid = 477021 -gfo_fid = 4555292 -ref_pid = 270789 -ref_fid = 2920436 -brc_pid = 231382 -brc_fid = 3408276 -dre_pid = 223565 -dre_fid = 3431261 -dra_pid = 314515 -dra_fid = 3514704 -jei_version = 4.16.1.302 -crt_version = 4.1.20.687 -top_pid = 245211 -top_fid = 2667280 -ctm_pid = 267602 -ctm_fid = 2915363 -grs_pid = 687577 -grs_fid = 4399621 - -# Debug mod compatibility -debug_de = false - -## Assetmover Dependencies -assetmover_version = 2.0 - -## Mixin Dependencies -mixinbooter_version = 7.0 -mixin_version = 0.8.3 -asm_debug_version = 5.2 -### should use 24.1.1 but 30.0+ has a vulnerability fix -guava_version = 30.0 -### should use 2.8.6 but 2.8.9+ has a vulnerability fix -gson_version = 2.8.9 - -## Test Dependencies -junit_version = 5.9.1 -hamcrest_version = 2.2 - -## Gradle Dependencies -foojay_version = 0.4.0 -idea_ext_version = 1.1.7 -rfg_version = 1.3.+ -java_version = 8 - -## Compile-Time Dependencies -annotations_version = 24.0.1 -curseforge_gradle_version = 1.0.+ -minotaur_version = 2.7.+ diff --git a/repositories.gradle b/repositories.gradle new file mode 100644 index 00000000..93ef1412 --- /dev/null +++ b/repositories.gradle @@ -0,0 +1,27 @@ +// Add any additional repositories for your dependencies here + +repositories { + maven { // MixinBooter + name 'Cleanroom Maven' + url 'https://maven.cleanroommc.com' + } + maven { // Mixin + name 'Sponge Maven' + url 'https://repo.spongepowered.org/maven' + } + maven { // CurseForge + name 'Curse Maven' + url 'https://www.cursemaven.com' + content { + includeGroup 'curse.maven' + } + } + maven { // CraftTweaker and JEI Backup + name 'BlameJared Maven' + url 'https://maven.blamejared.com' + } + maven { // Autoconfig and Autosave + name 'Mod Maven' + url 'https://modmaven.dev' + } +} diff --git a/settings.gradle b/settings.gradle index 18b43546..b0797c85 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,12 +2,14 @@ pluginManagement { repositories { maven { // RetroFuturaGradle - name = "GTNH Maven" - url = uri("http://jenkins.usrv.eu:8081/nexus/content/groups/public/") + name 'GTNH Maven' + //noinspection HttpUrlsUsage + url 'http://jenkins.usrv.eu:8081/nexus/content/groups/public/' allowInsecureProtocol = true + //noinspection GroovyAssignabilityCheck mavenContent { - includeGroup("com.gtnewhorizons") - includeGroup("com.gtnewhorizons.retrofuturagradle") + includeGroup 'com.gtnewhorizons' + includeGroup 'com.gtnewhorizons.retrofuturagradle' } } gradlePluginPortal() @@ -17,9 +19,16 @@ pluginManagement { } plugins { + id 'com.diffplug.blowdryerSetup' version '1.6.0' // Automatic toolchain provisioning - id("org.gradle.toolchains.foojay-resolver-convention") version "0.4.0" + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.4.0' id("com.gradle.enterprise") version "3.13.2" } -rootProject.name = archives_base_name +blowdryerSetup { + repoSubfolder 'spotless' + github('GregTechCEu/Buildscripts', 'commit', 'a1e1f2dfebb66f8fc652cd3e020b871fbd8604cb') + //devLocal '.' // Use this when testing config updates locally +} + +rootProject.name = modArchivesBaseName From 43f1871dad336e8322ff06b9329b3c8e84a80991 Mon Sep 17 00:00:00 2001 From: tier940 Date: Fri, 2 Jun 2023 10:10:06 +0900 Subject: [PATCH 2/7] =?UTF-8?q?=E3=83=AC=E3=83=93=E3=83=A5=E3=83=BC?= =?UTF-8?q?=E6=8C=87=E6=91=98=E3=81=AE=E5=8F=8D=E6=98=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dependencies.gradle | 12 ++++++------ repositories.gradle | 19 ------------------- 2 files changed, 6 insertions(+), 25 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 38f95dd8..10bb7c50 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -38,7 +38,7 @@ dependencies { implementation rfg.deobf("curse.maven:ae-additions-extra-cells-2-fork-493962:3814371") // Soft Dependencies - compileOnlyApi rfg.deobf("curse.maven:gregtech-food-option-477021:4555292") + runtimeOnly rfg.deobf("curse.maven:gregtech-food-option-477021:4555292") implementation "mezz.jei:jei_1.12.2:4.16.1.302" implementation "CraftTweaker2:CraftTweaker2-MC1120-Main:1.12-4.1.20.687" implementation rfg.deobf("curse.maven:top-245211:2667280") @@ -50,15 +50,15 @@ dependencies { //implementation rfg.deobf("curse.maven:groovyscript-687577:4399621") // Debug Draconic Evolution/Additions - compileOnlyApi rfg.deobf("curse.maven:redstone-flux-270789:2920436") + runtimeOnly rfg.deobf("curse.maven:redstone-flux-270789:2920436") compileOnlyApi rfg.deobf("curse.maven:brandons-core-231382:3408276") compileOnlyApi rfg.deobf("curse.maven:draconic-evolution-223565:3431261") compileOnlyApi rfg.deobf("curse.maven:draconicadditions-314515:3514704") if (project.debug_de.toBoolean()) { - implementation rfg.deobf("curse.maven:redstone-flux-270789:2920436") - implementation rfg.deobf("curse.maven:brandons-core-231382:3408276") - implementation rfg.deobf("curse.maven:draconic-evolution-223565:3431261") - implementation rfg.deobf("curse.maven:draconicadditions-314515:3514704") + runtimeOnly rfg.deobf("curse.maven:redstone-flux-270789:2920436") + runtimeOnly rfg.deobf("curse.maven:brandons-core-231382:3408276") + runtimeOnly rfg.deobf("curse.maven:draconic-evolution-223565:3431261") + runtimeOnly rfg.deobf("curse.maven:draconicadditions-314515:3514704") } // Boot error fix diff --git a/repositories.gradle b/repositories.gradle index 93ef1412..2bff9213 100644 --- a/repositories.gradle +++ b/repositories.gradle @@ -1,25 +1,6 @@ // Add any additional repositories for your dependencies here repositories { - maven { // MixinBooter - name 'Cleanroom Maven' - url 'https://maven.cleanroommc.com' - } - maven { // Mixin - name 'Sponge Maven' - url 'https://repo.spongepowered.org/maven' - } - maven { // CurseForge - name 'Curse Maven' - url 'https://www.cursemaven.com' - content { - includeGroup 'curse.maven' - } - } - maven { // CraftTweaker and JEI Backup - name 'BlameJared Maven' - url 'https://maven.blamejared.com' - } maven { // Autoconfig and Autosave name 'Mod Maven' url 'https://modmaven.dev' From 699b0ce4be0ae86ebd4a591590973d7234505936 Mon Sep 17 00:00:00 2001 From: tier940 Date: Fri, 2 Jun 2023 11:08:14 +0900 Subject: [PATCH 3/7] =?UTF-8?q?=E3=83=AC=E3=83=93=E3=83=A5=E3=83=BC?= =?UTF-8?q?=E6=8C=87=E6=91=98=E3=81=AE=E5=8F=8D=E6=98=A0+=E4=B8=8D?= =?UTF-8?q?=E8=A6=81=E3=81=A0=E3=81=A3=E3=81=9F=E4=BE=9D=E5=AD=98=E3=81=AE?= =?UTF-8?q?=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dependencies.gradle | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 10bb7c50..eaa421b5 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -38,11 +38,9 @@ dependencies { implementation rfg.deobf("curse.maven:ae-additions-extra-cells-2-fork-493962:3814371") // Soft Dependencies - runtimeOnly rfg.deobf("curse.maven:gregtech-food-option-477021:4555292") - implementation "mezz.jei:jei_1.12.2:4.16.1.302" implementation "CraftTweaker2:CraftTweaker2-MC1120-Main:1.12-4.1.20.687" - implementation rfg.deobf("curse.maven:top-245211:2667280") implementation rfg.deobf("curse.maven:ctm-267602:2915363") + compileOnly rfg.deobf("curse.maven:gregtech-food-option-477021:4555292") // use a local jar for GroovyScript to avoid a bug from Mixin and ForgeGradle, // causing crashes at run-time when deobfuscated @@ -50,10 +48,10 @@ dependencies { //implementation rfg.deobf("curse.maven:groovyscript-687577:4399621") // Debug Draconic Evolution/Additions - runtimeOnly rfg.deobf("curse.maven:redstone-flux-270789:2920436") - compileOnlyApi rfg.deobf("curse.maven:brandons-core-231382:3408276") - compileOnlyApi rfg.deobf("curse.maven:draconic-evolution-223565:3431261") - compileOnlyApi rfg.deobf("curse.maven:draconicadditions-314515:3514704") + compileOnly rfg.deobf("curse.maven:redstone-flux-270789:2920436") + compileOnly rfg.deobf("curse.maven:brandons-core-231382:3408276") + compileOnly rfg.deobf("curse.maven:draconic-evolution-223565:3431261") + compileOnly rfg.deobf("curse.maven:draconicadditions-314515:3514704") if (project.debug_de.toBoolean()) { runtimeOnly rfg.deobf("curse.maven:redstone-flux-270789:2920436") runtimeOnly rfg.deobf("curse.maven:brandons-core-231382:3408276") From c030bab9daf86844b3fff026752c651b2d146185 Mon Sep 17 00:00:00 2001 From: tier940 Date: Fri, 2 Jun 2023 13:04:36 +0900 Subject: [PATCH 4/7] fix cicd --- .github/workflows/auto-build.yml | 21 ++++--- .github/workflows/publish.yml | 71 ++++++++++++++++++++++++ .github/workflows/release.yml | 46 --------------- .github/workflows/update_buildscript.yml | 42 ++++++++++++++ 4 files changed, 126 insertions(+), 54 deletions(-) create mode 100644 .github/workflows/publish.yml delete mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/update_buildscript.yml diff --git a/.github/workflows/auto-build.yml b/.github/workflows/auto-build.yml index 647074fd..9afe5fed 100644 --- a/.github/workflows/auto-build.yml +++ b/.github/workflows/auto-build.yml @@ -15,12 +15,11 @@ jobs: - name: Checkout uses: actions/checkout@v3 - - name: Set up JDK 8 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: - java-version: 8 + java-version: 17 distribution: zulu - cache: gradle - name: Validate Gradle wrapper uses: gradle/wrapper-validation-action@v1 @@ -28,11 +27,17 @@ jobs: - name: Build with Gradle uses: gradle/gradle-build-action@v2 with: - arguments: build --scan --no-daemon + arguments: 'build --build-cache --daemon' # use the daemon here so the rest of the process is faster generate-job-summary: true + gradle-home-cache-includes: | + caches + jdks + notifications + wrapper - - name: Upload Jars - uses: actions/upload-artifact@v3 + - name: Publish to GitHub + uses: softprops/action-gh-release@v1 with: - name: GTExpert-Core - path: build/libs/*.jar + files: "build/libs/*.jar" + generate_release_notes: true + fail_on_unmatched_files: true diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000..8e49d932 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,71 @@ +# Publishes built jars to distribution platforms +name: Publish + +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' # any semver tag, e.g. v1.2.3 + +env: + # link to the changelog with a format code for the version + CHANGELOG_LOCATION: "Changelog is available [here](https://github.com/${{github.repository}}/releases/tag/${{github.ref_name}})" + # type of release + RELEASE_TYPE: "beta" + +jobs: + Publish: + runs-on: ubuntu-latest + + permissions: + contents: write # needed to create GitHub releases + + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + + - name: Check for Duplicate Tags + run: | + if git rev-parse -q --verify "refs/tags/${{ github.ref }}" >/dev/null; then + echo "Tag already exists. A version bump is required." + exit 1 + fi + + - name: Setup Java + uses: actions/setup-java@v3 + with: + distribution: zulu + java-version: 17 + + - name: Build Project + uses: gradle/gradle-build-action@v2 + with: + arguments: 'build --build-cache --daemon' # use the daemon here so the rest of the process is faster + generate-job-summary: false + gradle-home-cache-includes: | + caches + jdks + notifications + wrapper + + - name: Publish to GitHub + uses: softprops/action-gh-release@v1 + with: + files: "build/libs/*.jar" + generate_release_notes: true + fail_on_unmatched_files: true + + - name: Publish to Curseforge + uses: gradle/gradle-build-action@v2 + env: + CURSEFORGE_API_KEY: "${{secrets.CURSEFORGE_API_KEY}}" + CURSEFORGE_PROJECT_ID: "${{secrets.CURSEFORGE_PROJECT_ID}}" + CHANGELOG_LOCATION: "${{env.CHANGELOG_LOCATION}}" + RELEASE_TYPE: "${{env.RELEASE_TYPE}}" + with: + arguments: 'curseforge --daemon' + generate-job-summary: false + gradle-home-cache-includes: | + caches + jdks + notifications + wrapper diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 3f7ff7a4..00000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: Deploy CoreMod -on: - push: - tags: - - 'v[0-9]+.[0-9]+.[0-9]+' # any semver tag, e.g. v1.2.3 - -env: - # link to the changelog with a format code for the version - CHANGELOG_LOCATION: "Changelog is available [here](https://github.com/${{github.repository}}/releases/tag/${{github.ref_name}})" - # type of release - RELEASE_TYPE: "beta" - -jobs: - deploy: - runs-on: ubuntu-latest - - permissions: - contents: write # needed to create GitHub releases - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Set up JDK 8 - uses: actions/setup-java@v3 - with: - java-version: 8 - distribution: zulu - cache: gradle - - - name: Validate Gradle wrapper - uses: gradle/wrapper-validation-action@v1 - - - name: Build with Gradle - uses: gradle/gradle-build-action@v2 - with: - arguments: build --no-daemon - generate-job-summary: false - - - name: Create GitHub Release - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') - with: - prerelease: false - generate_release_notes: true - files: build/libs/*.jar diff --git a/.github/workflows/update_buildscript.yml b/.github/workflows/update_buildscript.yml new file mode 100644 index 00000000..9a2c6a00 --- /dev/null +++ b/.github/workflows/update_buildscript.yml @@ -0,0 +1,42 @@ +# Checks daily to see if the buildscript is in need of an update +name: Buildscript Updating + +on: + workflow_dispatch: + schedule: + - cron: "0 0 * * *" # "min hr day month year", so run once per day + +jobs: + buildscript-update: + runs-on: ubuntu-latest + # Avoid running this workflow on forks + if: github.repository == 'GregTechCEu/GregTech' + permissions: + contents: write + pull-requests: write + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Ensure build script version is up to date + id: update-buildscript + run: | + curl https://raw.githubusercontent.com/GregTechCEu/Buildscripts/master/build.gradle --output build.gradle + new_version=$(head -1 build.gradle | sed -r 's|//version: (.*)|\1|g') + echo "NEW_VERSION=$new_version" >> "$GITHUB_OUTPUT" + + - name: Create Pull Request + id: create-pull-request + uses: peter-evans/create-pull-request@v4 + env: + GITHUB_TOKEN: ${{ secrets.BUILDSCRIPT_UPDATER_TOKEN }} + with: + token: ${{ secrets.BUILDSCRIPT_UPDATER_TOKEN }} + committer: GitHub + author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com> + add-paths: build.gradle + commit-message: 'update build script version to ${{ steps.update-buildscript.outputs.NEW_VERSION }}' + branch: gha-update-buildscript + title: Update build script version to ${{ steps.update-buildscript.outputs.NEW_VERSION }} + body: This pull request is created by the buildscript-update workflow + labels: ignore changelog From 0a781d2593ecbd5e98f0000c8f088e3c2558db4a Mon Sep 17 00:00:00 2001 From: tier940 Date: Sun, 4 Jun 2023 10:48:54 +0900 Subject: [PATCH 5/7] =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=9D=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 6 ++++-- gradle.properties | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 22f33405..594334f1 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1685514775 +//version: 1685741895 /* * DO NOT CHANGE THIS FILE! * Also, you may replace this file at any time if there is an update available. @@ -484,6 +484,8 @@ processResources { 'modname': modName ) } + + rename '(.+_at.cfg)', 'META-INF/$1' } // Automatically generate a mixin json file if it does not already exist @@ -936,7 +938,7 @@ tasks.register('faq') { "To add new repositories to your project, place them in 'repositories.gradle'.\n" + "If you need additional gradle code to run, you can place it in a file named 'addon.gradle' (or either of the above, up to you for organization).\n\n" + "If your build fails to recognize the syntax of newer Java versions, enable Jabel in your 'gradle.properties' under the option name 'enableModernJavaSyntax'.\n" + - "To see information on how to configure your IDE properly for Java 17, see https://github.com/GregTechCEu/Buildscripts/blob/master/jabel.md\n\n" + + "To see information on how to configure your IDE properly for Java 17, see https://github.com/GregTechCEu/Buildscripts/blob/master/docs/jabel.md\n\n" + "Report any issues or feature requests you have for this build script to https://github.com/GregTechCEu/Buildscripts/issues\n") } } diff --git a/gradle.properties b/gradle.properties index 76e664b1..fe3d32ce 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -modName = GTExportCore +modName = GTExpertCore # This is a case-sensitive string to identify your mod. Convention is to use lower case. modId = gtexpert @@ -8,7 +8,7 @@ modGroup = gtexpert modVersion = 1.3.15-beta # The name of your jar when you produce builds, not including any versioning info -modArchivesBaseName = GTExportCore +modArchivesBaseName = GTExpertCore # Will update your build.gradle automatically whenever an update is available autoUpdateBuildScript = true From 0daef11b4544c968598d5b54de78f114c9db7376 Mon Sep 17 00:00:00 2001 From: tier940 Date: Sat, 17 Jun 2023 13:31:22 +0900 Subject: [PATCH 6/7] update --- build.gradle | 231 ++++++++++++++++++++++++++++++-------------- dependencies.gradle | 8 ++ gradle.properties | 11 ++- settings.gradle | 6 +- 4 files changed, 176 insertions(+), 80 deletions(-) diff --git a/build.gradle b/build.gradle index 594334f1..a364295b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: 1685741895 +//version: 1686205143 /* * DO NOT CHANGE THIS FILE! * Also, you may replace this file at any time if there is an update available. @@ -22,9 +22,9 @@ plugins { id 'eclipse' id 'maven-publish' id 'org.jetbrains.gradle.plugin.idea-ext' version '1.1.7' - id 'com.gtnewhorizons.retrofuturagradle' version '1.3.+' - id 'net.darkhax.curseforgegradle' version '1.0.+' apply false - id 'com.modrinth.minotaur' version '2.7.+' apply false + id 'com.gtnewhorizons.retrofuturagradle' version '1.3.19' + id 'net.darkhax.curseforgegradle' version '1.0.14' apply false + id 'com.modrinth.minotaur' version '2.8.0' apply false id 'com.diffplug.spotless' version '6.13.0' apply false id 'com.palantir.git-version' version '3.0.0' apply false id 'com.github.johnrengelman.shadow' version '8.1.1' apply false @@ -43,7 +43,6 @@ def out = services.get(StyledTextOutputFactory).create('an-output') checkPropertyExists("modName") checkPropertyExists("modId") checkPropertyExists("modGroup") -checkPropertyExists("modVersion") checkPropertyExists("minecraftVersion") // hard-coding this makes it harder to immediately tell what version a mod is in (even though this only really supports 1.12.2) checkPropertyExists("apiPackage") checkPropertyExists("accessTransformersFile") @@ -53,6 +52,7 @@ checkPropertyExists("coreModClass") checkPropertyExists("containsMixinsAndOrCoreModOnly") // Optional properties: we can assume some default behavior if these are missing +propertyDefaultIfUnset("modVersion", "") propertyDefaultIfUnset("autoUpdateBuildScript", false) propertyDefaultIfUnset("modArchivesBaseName", project.modId) propertyDefaultIfUnsetWithEnvVar("developmentEnvironmentUserName", "Developer", "DEV_USERNAME") @@ -67,11 +67,12 @@ propertyDefaultIfUnset("forceEnableMixins", false) propertyDefaultIfUnset("usesShadowedDependencies", false) propertyDefaultIfUnset("minimizeShadowedDependencies", true) propertyDefaultIfUnset("relocateShadowedDependencies", true) -propertyDefaultIfUnset("modrinthProjectId", "") +propertyDefaultIfUnsetWithEnvVar("modrinthProjectId", "", "MODRINTH_PROJECT_ID") propertyDefaultIfUnset("modrinthRelations", "") -propertyDefaultIfUnset("curseForgeProjectId", "") +propertyDefaultIfUnsetWithEnvVar("curseForgeProjectId", "", "CURSEFORGE_PROJECT_ID") propertyDefaultIfUnset("curseForgeRelations", "") -propertyDefaultIfUnset("releaseType", "release") +propertyDefaultIfUnsetWithEnvVar("releaseType", "release", "RELEASE_TYPE") +propertyDefaultIfUnset("generateDefaultChangelog", false) propertyDefaultIfUnset("customMavenPublishUrl", "") propertyDefaultIfUnset("enableModernJavaSyntax", false) propertyDefaultIfUnset("enableSpotless", false) @@ -190,7 +191,7 @@ if (enableSpotless.toBoolean()) { } } -// Git submodules +// Git version checking, also checking for if this is a submodule if (project.file('.git/HEAD').isFile() || project.file('.git').isFile()) { apply plugin: 'com.palantir.git-version' } @@ -241,8 +242,27 @@ tasks.withType(ScalaCompile).configureEach { } +// Allow others using this buildscript to have custom gradle code run +if (getFile('addon.gradle').exists()) { + apply from: 'addon.gradle' +} + + // Configure Minecraft +// Try to gather mod version from git tags if version is not manually specified +if (!modVersion) { + try { + modVersion = gitVersion() + } catch (Exception ignored) { + out.style(Style.Failure).text( + "Mod version could not be determined! Property 'modVersion' is not set, and either git is not installed or no git tags exist.\n" + + "Either specify a mod version in 'gradle.properties', or create at least one tag in git for this project." + ) + modVersion = 'NO-GIT-TAG-SET' + } +} + version = modVersion group = modGroup archivesBaseName = modArchivesBaseName @@ -286,12 +306,6 @@ tasks.named('processIdeaSettings').configure { } -// Allow others using this buildscript to have custom gradle code run -if (getFile('addon.gradle').exists()) { - apply from: 'addon.gradle' -} - - // Repositories // Allow unsafe repos but warn @@ -485,7 +499,12 @@ processResources { ) } - rename '(.+_at.cfg)', 'META-INF/$1' + if (accessTransformersFile) { + String[] ats = accessTransformersFile.split(',') + ats.each { at -> + rename "(${at})", 'META-INF/$1' + } + } } // Automatically generate a mixin json file if it does not already exist @@ -521,7 +540,6 @@ tasks.register('generateAssets') { "dependencies": [] }] """ - mcmodInfoFile } // mixins.{modid}.json @@ -546,10 +564,8 @@ tasks.register('generateAssets') { } } -if (usesMixins.toBoolean()) { - tasks.named('processResources').configure { - dependsOn('generateAssets') - } +tasks.named('processResources').configure { + dependsOn('generateAssets') } jar { @@ -696,10 +712,9 @@ idea { // Deployment - +def final modrinthApiKey = providers.environmentVariable('MODRINTH_API_KEY') +def final cfApiKey = providers.environmentVariable('CURSEFORGE_API_KEY') final boolean isCIEnv = providers.environmentVariable('CI').getOrElse('false').toBoolean() -def final changelogEnv = providers.environmentVariable('CHANGELOG_LOCATION') -File changelogFile = new File(changelogEnv.getOrElse('CHANGELOG.md')) if (isCIEnv || deploymentDebug.toBoolean()) { artifacts { @@ -712,59 +727,92 @@ if (isCIEnv || deploymentDebug.toBoolean()) { } } -// Curseforge -def final cfApiKey = providers.environmentVariable('CURSEFORGE_API_KEY') +// Changelog generation +tasks.register('generateChangelog') { + group = 'GT Buildscript' + description = 'Generate a default changelog of all commits since the last tagged git commit' + onlyIf { + generateDefaultChangelog.toBoolean() + } + doLast { + def lastTag = getLastTag() + + def changelog = runShell(([ + "git", + "log", + "--date=format:%d %b %Y", + "--pretty=%s - **%an** (%ad)", + "${lastTag}..HEAD" + ] + (sourceSets.main.java.srcDirs + sourceSets.main.resources.srcDirs) + .collect { ['--', it] }).flatten()) + + if (changelog) { + changelog = "Changes since ${lastTag}:\n${{("\n" + changelog).replaceAll("\n", "\n* ")}}" + } + def f = getFile('build/changelog.md') + changelog = changelog ?: 'There have been no changes.' + f.write(changelog, 'UTF-8') + + // Set changelog for Modrinth + if (modrinthApiKey.isPresent() || deploymentDebug.toBoolean()) { + modrinth.changelog.set(changelog) + } + } +} + if (cfApiKey.isPresent() || deploymentDebug.toBoolean()) { apply plugin: 'net.darkhax.curseforgegradle' //noinspection UnnecessaryQualifiedReference tasks.register('curseforge', net.darkhax.curseforgegradle.TaskPublishCurseForge) { - apiToken = cfApiKey.get() - def projectIdVar = providers.environmentVariable('CURSEFORGE_PROJECT_ID') - - def mainFile = upload(projectIdVar.getOrElse(curseForgeProjectId), reobfJar) - def changelogRaw = changelogFile.exists() ? changelogFile.getText('UTF-8') : "" - - mainFile.releaseType = getReleaseType() - mainFile.changelog = changelogRaw - mainFile.changelogType = 'markdown' - mainFile.addModLoader 'Forge' - mainFile.addJavaVersion "Java 8" - mainFile.addGameVersion minecraftVersion - - if (curseForgeRelations.size() != 0) { - String[] deps = curseForgeRelations.split(';') - deps.each { dep -> - if (dep.size() == 0) { - return - } - String parts = dep.split(':') - String type = parts[0], slug = parts[1] - if(!(type in ['requiredDependency', 'embeddedLibrary', 'optionalDependency', 'tool', 'incompatible'])) { - throw new Exception('Invalid Curseforge dependency type: ' + type) + disableVersionDetection() + debugMode = deploymentDebug.toBoolean() + apiToken = cfApiKey.getOrElse('debug_token') + + doFirst { + def mainFile = upload(curseForgeProjectId, reobfJar) + def changelogFile = getChangelog() + def changelogRaw = changelogFile.exists() ? changelogFile.getText('UTF-8') : "" + + mainFile.displayName = "${modName}: ${modVersion}" + mainFile.releaseType = getReleaseType() + mainFile.changelog = changelogRaw + mainFile.changelogType = 'markdown' + mainFile.addModLoader 'Forge' + mainFile.addJavaVersion "Java 8" + mainFile.addGameVersion minecraftVersion + + if (curseForgeRelations.size() != 0) { + String[] deps = curseForgeRelations.split(';') + deps.each { dep -> + if (dep.size() == 0) { + return + } + String[] parts = dep.split(':') + String type = parts[0], slug = parts[1] + if (!(type in ['requiredDependency', 'embeddedLibrary', 'optionalDependency', 'tool', 'incompatible'])) { + throw new Exception('Invalid Curseforge dependency type: ' + type) + } + mainFile.addRelation(slug, type) } - mainFile.addRelation(slug, type) } - } - for (artifact in getSecondaryArtifacts()) { - def additionalFile = mainFile.withAdditionalFile(artifact) - additionalFile.changelog = changelogRaw + for (artifact in getSecondaryArtifacts()) { + def additionalFile = mainFile.withAdditionalFile(artifact) + additionalFile.changelog = changelogRaw + } } - disableVersionDetection() - debugMode = deploymentDebug.toBoolean() } tasks.curseforge.dependsOn(build) + tasks.curseforge.dependsOn('generateChangelog') } -// Modrinth -def final modrinthApiKey = providers.environmentVariable('MODRINTH_API_KEY') if (modrinthApiKey.isPresent() || deploymentDebug.toBoolean()) { apply plugin: 'com.modrinth.minotaur' - def final projectIdVar = providers.environmentVariable('MODRINTH_PROJECT_ID') + def final changelogFile = getChangelog() modrinth { - token = modrinthApiKey.get() - projectId = projectIdVar.getOrElse(modrinthProjectId) + token = modrinthApiKey.getOrElse('debug_token') + projectId = modrinthProjectId changelog = changelogFile.exists() ? changelogFile.getText('UTF-8') : "" versionType = getReleaseType() versionNumber = modVersion @@ -781,11 +829,12 @@ if (modrinthApiKey.isPresent() || deploymentDebug.toBoolean()) { return } String[] parts = dep.split(':') - String qual = parts[0].split('-') + String[] qual = parts[0].split('-') addModrinthDep(qual[0], qual[1], parts[1]) } } tasks.modrinth.dependsOn(build) + tasks.modrinth.dependsOn('generateChangelog') } def addModrinthDep(String scope, String type, String name) { @@ -839,6 +888,37 @@ if (customMavenPublishUrl) { } } +def getSecondaryArtifacts() { + def secondaryArtifacts = [usesShadowedDependencies.toBoolean() ? tasks.shadowJar : tasks.jar] + if (!noPublishedSources.toBoolean()) secondaryArtifacts += [sourcesJar] + if (apiPackage) secondaryArtifacts += [apiJar] + return secondaryArtifacts +} + +def getReleaseType() { + String type = project.releaseType + if (!(type in ['release', 'beta', 'alpha'])) { + throw new Exception("Release type invalid! Found \"" + type + "\", allowed: \"release\", \"beta\", \"alpha\"") + } + return type +} + +/* + * If CHANGELOG_LOCATION env var is set, that takes highest precedence. + * Next, if 'generateDefaultChangelog' option is enabled, use that. + * Otherwise, try to use a CHANGELOG.md file at root directory. + */ +def getChangelog() { + def final changelogEnv = providers.environmentVariable('CHANGELOG_LOCATION') + if (changelogEnv.isPresent()) { + return new File(changelogEnv.get()) + } + if (generateDefaultChangelog.toBoolean()) { + return getFile('build/changelog.md') + } + return getFile('CHANGELOG.md') +} + // Buildscript updating @@ -971,17 +1051,22 @@ def propertyDefaultIfUnsetWithEnvVar(String propertyName, defaultValue, String e } } -def getSecondaryArtifacts() { - def secondaryArtifacts = [usesShadowedDependencies.toBoolean() ? tasks.shadowJar : tasks.jar] - if (!noPublishedSources.toBoolean()) secondaryArtifacts += [sourcesJar] - if (apiPackage) secondaryArtifacts += [apiJar] - return secondaryArtifacts -} +static runShell(command) { + def process = command.execute() + def outputStream = new StringBuffer() + def errorStream = new StringBuffer() + process.waitForProcessOutput(outputStream, errorStream) -def getReleaseType() { - String type = releaseType - if (!(type in ['release', 'beta', 'alpha'])) { - throw new Exception("Release type invalid! Found \"" + type + "\", allowed: \"release\", \"beta\", \"alpha\"") + errorStream.toString().with { + if (it) { + throw new GradleException("Error executing ${command}:\n> ${it}") + } } - return type + return outputStream.toString().trim() +} + +def getLastTag() { + def githubTag = providers.environmentVariable('GITHUB_TAG') + return runShell('git describe --abbrev=0 --tags ' + + (githubTag.isPresent() ? runShell('git rev-list --tags --skip=1 --max-count=1') : '')) } diff --git a/dependencies.gradle b/dependencies.gradle index eaa421b5..e0f29701 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -17,6 +17,8 @@ * To add a mod with CurseMaven, replace '("g:n:v:c")' in the above with 'rfg.deobf("curse.maven:project_slug-project_id:file_id")' * Example: implementation rfg.deobf("curse.maven:gregtech-ce-unofficial-557242:4527757") * + * To shadow a dependency, use 'shadowImplementation'. For more info, see https://github.com/GregTechCEu/Buildscripts/blob/master/docs/shadow.md + * * For more details, see https://docs.gradle.org/8.0.1/userguide/java_library_plugin.html#sec:java_library_configurations_graph */ dependencies { @@ -59,6 +61,12 @@ dependencies { runtimeOnly rfg.deobf("curse.maven:draconicadditions-314515:3514704") } + // Debug Chisel + compileOnly rfg.deobf("curse.maven:chisel-235279:2915375") + if (project.debug_chisel.toBoolean()) { + implementation rfg.deobf("curse.maven:chisel-235279:2915375") + } + // Boot error fix runtimeOnly (files("libs/EnderCore-1.12.2-0.5.76-core.jar")) } diff --git a/gradle.properties b/gradle.properties index fe3d32ce..1dd1c2a7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,6 +17,7 @@ minecraftVersion = 1.12.2 # Debug mod compatibility debug_de = false +debug_chisel = false # Select a username for testing your mod with breakpoints. You may leave this empty for a random username each time you # restart Minecraft in development. Choose this dependent on your mod: @@ -107,12 +108,17 @@ curseForgeProjectId = 851103 # Where type can be one of [requiredDependency, embeddedLibrary, optionalDependency, tool, incompatible], # and the name is the CurseForge project slug of the other mod. # Example: requiredDependency:railcraft;embeddedLibrary:cofhlib;incompatible:buildcraft -curseForgeRelations = +curseForgeRelations = # This project's release type on CurseForge and/or Modrinth +# Alternatively this can be set with the 'RELEASE_TYPE' environment variable. # Allowed types: release, beta, alpha releaseType = beta +# Generate a default changelog for releases. Requires git to be installed, as it uses it to generate a changelog of +# commits since the last tagged release. +generateDefaultChangelog = false + # Prevent the source code from being published noPublishedSources = false @@ -148,7 +154,4 @@ deploymentDebug = false org.gradle.logging.stacktrace = all # Sets default memory used for gradle commands. Can be overridden by user or command line properties. # This is required to provide enough memory for the Minecraft decompilation process. -org.gradle.daemon = true -org.gradle.parallel = true -org.gradle.caching = true org.gradle.jvmargs = -Xmx3G -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -Dfile.encoding=UTF-8 diff --git a/settings.gradle b/settings.gradle index b0797c85..98eca370 100644 --- a/settings.gradle +++ b/settings.gradle @@ -27,8 +27,8 @@ plugins { blowdryerSetup { repoSubfolder 'spotless' - github('GregTechCEu/Buildscripts', 'commit', 'a1e1f2dfebb66f8fc652cd3e020b871fbd8604cb') - //devLocal '.' // Use this when testing config updates locally + github 'GregTechCEu/Buildscripts', 'tag', 'v1.0.0' + //devLocal '.' // Use this when testing config updated locally } -rootProject.name = modArchivesBaseName +rootProject.name = rootProject.projectDir.getName() From f5866ef9759736fcda535ec07cd73ed102b7993b Mon Sep 17 00:00:00 2001 From: tier940 Date: Sat, 17 Jun 2023 21:27:47 +0900 Subject: [PATCH 7/7] true enableSpotless --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 1dd1c2a7..16c840b1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -137,7 +137,7 @@ customMavenPublishUrl = # By default this will use the files found here: https://github.com/GregTechCEu/Buildscripts/tree/master/spotless # to format your code. However, you can create your own version of these files and place them in your project's # root directory to apply your own formatting options instead. -enableSpotless = false +enableSpotless = true # Enable JUnit testing platform used for testing your code. # Uses JUnit 5. See guide and documentation here: https://junit.org/junit5/docs/current/user-guide/