//version: 1656003793falsepattern75 /* 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/FalsePattern/ExampleMod1.7.10/blob/main/build.gradle for updates. */ import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar 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 java.nio.file.Files import java.nio.file.Paths import java.util.concurrent.TimeUnit import java.util.zip.ZipEntry import java.util.zip.ZipInputStream import java.util.zip.ZipOutputStream buildscript { repositories { mavenLocal() maven { name = "forge" url = "https://mvn.falsepattern.com/forge" } maven { name = "sonatype" url = "https://oss.sonatype.org/content/repositories/snapshots/" } maven { name = "Scala CI dependencies" url = "https://repo1.maven.org/maven2/" } maven { name = "jitpack" url = "https://mvn.falsepattern.com/jitpack/" } maven { name = "mavenpattern" url = "https://mvn.falsepattern.com/releases/" } maven { name = "usrv" url = "https://mvn.falsepattern.com/usrv/" } } dependencies { classpath 'net.minecraftforge.gradle:ForgeGradle:1.2.11' classpath 'com.falsepattern:jtweaker:0.2.1' } } plugins { id 'java-library' id 'idea' id 'eclipse' id 'scala' id 'maven-publish' id 'org.jetbrains.kotlin.jvm' version '1.5.30' apply false id 'org.jetbrains.kotlin.kapt' version '1.5.30' apply false id 'com.google.devtools.ksp' version '1.5.30-1.0.0' apply false id 'org.ajoberstar.grgit' version '4.1.1' id 'com.github.johnrengelman.shadow' version '4.0.4' id 'com.palantir.git-version' version '0.13.0' id 'de.undercouch.download' version '5.0.1' id 'com.github.gmazzo.buildconfig' version '3.0.3' apply false id 'com.modrinth.minotaur' version '2.+' apply false id 'com.matthewprenger.cursegradle' version '1.4.0' apply false } apply plugin: 'com.falsepattern.jtweaker' def out = services.get(StyledTextOutputFactory).create('an-output') apply plugin: 'forge' def projectJavaVersion = JavaLanguageVersion.of(8) java { toolchain { languageVersion.set(projectJavaVersion) } } idea { module { inheritOutputDirs = true downloadJavadoc = true downloadSources = true } } if(JavaVersion.current() != JavaVersion.VERSION_1_8) { throw new GradleException("This project requires Java 8, but it's running on " + JavaVersion.current()) } checkPropertyExists("modName") checkPropertyExists("modId") checkPropertyExists("modGroup") checkPropertyExists("autoUpdateBuildScript") checkPropertyExists("minecraftVersion") checkPropertyExists("forgeVersion") checkPropertyExists("replaceGradleTokenInFile") checkPropertyExists("gradleTokenModId") checkPropertyExists("gradleTokenModName") checkPropertyExists("gradleTokenVersion") checkPropertyExists("gradleTokenGroupName") checkPropertyExists("apiPackage") checkPropertyExists("accessTransformersFile") checkPropertyExists("usesMixins") checkPropertyExists("mixinPlugin") checkPropertyExists("mixinsPackage") checkPropertyExists("coreModClass") checkPropertyExists("containsMixinsAndOrCoreModOnly") checkPropertyExists("usesShadowedDependencies") checkPropertyExists("developmentEnvironmentUserName") //Properties added in fork propertyDefaultIfUnset("skipBuildScriptUpdateCheck", false) propertyDefaultIfUnset("repositoryURL", "") propertyDefaultIfUnset("repositoryName", "") propertyDefaultIfUnset("mavenGroupId", "") propertyDefaultIfUnset("mavenArtifactId", "") propertyDefaultIfUnset("hasMixinDeps", false) propertyDefaultIfUnset("mixinConfigs", "") propertyDefaultIfUnset("mixinPluginPreInit", "") propertyDefaultIfUnset("mixinPluginMinimumVersion", "0.8.5") propertyDefaultIfUnset("remapStubs", false) propertyDefaultIfUnset("apiPackages", null) propertyDefaultIfUnset("apiPackagesNoRecurse", null) propertyDefaultIfUnset("modrinthProjectId", "") propertyDefaultIfUnset("modrinthDependencies", "") propertyDefaultIfUnset("curseForgeProjectId", "") propertyDefaultIfUnset("curseForgeRelations", "") propertyDefaultIfUnset("changelog", "") propertyDefaultIfUnset("remoteMappings", "https://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/") propertyDefaultIfUnset("mappingsChannel", "stable") propertyDefaultIfUnset("mappingsVersion", "12") String javaSourceDir = "src/main/java/" String scalaSourceDir = "src/main/scala/" String kotlinSourceDir = "src/main/kotlin/" def verifyPackage(thePackage, propName) { String javaSourceDir = "src/main/java/" String scalaSourceDir = "src/main/scala/" String kotlinSourceDir = "src/main/kotlin/" String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + thePackage.toString().replaceAll("\\.", "/") String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + thePackage.toString().replaceAll("\\.", "/") String targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + thePackage.toString().replaceAll("\\.", "/") if(!(getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists() || getFile(targetPackageKotlin).exists())) { throw new GradleException("Could not resolve \"${propName}\"! Could not find " + targetPackageJava + " or " + targetPackageScala + " or " + targetPackageKotlin) } } verifyPackage("", "modGroup") if(apiPackage) { verifyPackage(apiPackage, "apiPackage") } if (apiPackages) { apiPackages.tokenize(';').forEach { it -> verifyPackage(it, "apiPackages")} } if (apiPackagesNoRecurse) { apiPackagesNoRecurse.tokenize(';').forEach { it -> verifyPackage(it, "apiPackagesNoRecurse")} } if(accessTransformersFile) { String targetFile = "src/main/resources/META-INF/" + accessTransformersFile if(!getFile(targetFile).exists()) { throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) } } if(usesMixins.toBoolean()) { if(mixinsPackage.isEmpty()) { throw new GradleException("\"usesMixins\" requires \"mixinsPackage\" to be set!") } String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") String targetPackageKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") 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 + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".scala" String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" String targetFileKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".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) { String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".scala" String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" String targetFileKotlin = kotlinSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".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.all { 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 = modGroup if(project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { archivesBaseName = customArchiveBaseName } else { archivesBaseName = modId } archivesBaseName += "-mc" + minecraftVersion minecraft { version = minecraftVersion + "-" + forgeVersion + "-" + minecraftVersion runDir = "run" if (replaceGradleTokenInFile) { for (file in replaceGradleTokenInFile.split(',')) { replaceIn file } if(gradleTokenModId) { replace gradleTokenModId, modId } if(gradleTokenModName) { replace gradleTokenModName, modName } if(gradleTokenVersion) { replace gradleTokenVersion, modVersion } if(gradleTokenGroupName) { replace gradleTokenGroupName, modGroup } } } if(file("addon.gradle").exists()) { apply from: "addon.gradle" } apply from: 'repositories.gradle' if(file('repositories_override.gradle').exists()) { apply from: 'repositories_override.gradle' } configurations { for (config in [shadowImplementation, shadowCompile, shadeCompile]) { implementation.extendsFrom(shadeCompile) compileClasspath.extendsFrom(config) runtimeClasspath.extendsFrom(config) testCompileClasspath.extendsFrom(config) testRuntimeClasspath.extendsFrom(config) } } repositories { maven { name = "Overmind forge repo mirror" url = "https://gregtech.overminddl1.com/" } if(usesMixins.toBoolean() || hasMixinDeps.toBoolean()) { maven { name = "sponge" url = "https://mvn.falsepattern.com/releases" } maven { name = "sponge2" url = "https://mvn.falsepattern.com/sponge" } maven { name = "jitpack" url = "https://mvn.falsepattern.com/jitpack/" } } } def unimixinsVersion = "0.1.15" 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("com.github.LegacyModdingMC.UniMixins:unimixins-all-1.7.10:$unimixinsVersion:dev") implementation("com.github.LegacyModdingMC.UniMixins:unimixins-all-1.7.10:$unimixinsVersion:dev") runtimeOnly('org.jetbrains:intellij-fernflower:1.2.1.16') } else if(hasMixinDeps.toBoolean()) { runtimeOnly("com.github.LegacyModdingMC.UniMixins:unimixins-all-1.7.10:$unimixinsVersion:dev") } // Latest LWJGL implementation "org.lwjgl.lwjgl:lwjgl:2.9.4-nightly-20150209" implementation "org.lwjgl.lwjgl:lwjgl_util:2.9.4-nightly-20150209" minecraftNatives "org.lwjgl.lwjgl:lwjgl-platform:2.9.4-nightly-20150209" minecraftDeps "org.lwjgl.lwjgl:lwjgl:2.9.4-nightly-20150209" minecraftDeps "org.lwjgl.lwjgl:lwjgl_util:2.9.4-nightly-20150209" } if(usesMixins.toBoolean()) { configurations.implementation.dependencies.each { if (it instanceof ExternalModuleDependency) { it.exclude module: "SpongeMixins" it.exclude module: "SpongePoweredMixin" it.exclude module: "00gasstation-mc1.7.10" it.exclude module: "gtnhmixins" } } } apply from: 'dependencies.gradle' if(file('dependencies_override.gradle').exists()) { apply from: 'dependencies_override.gradle' } def mixinDir = new File(project.buildDir, 'mixins') if (!mixinDir.exists()) { mixinDir.mkdirs() } def mixingConfigRefMap = "mixins." + modId + ".refmap.json" def srgFile = new File(project.buildDir, 'srgs/mcp-srg.srg') def mixinSrg = new File(mixinDir, "${mixingConfigRefMap}.srg") def mixinRefMap = new File(mixinDir, mixingConfigRefMap) task generateAssets { if(usesMixins.toBoolean() && !mixinPlugin.isEmpty()) { getFile("/src/main/resources/mixins." + modId + ".json").text = """{ "required": true, "minVersion": "${mixinPluginMinimumVersion}", "package": "${modGroup}.${mixinsPackage}", "plugin": "${modGroup}.${mixinPlugin}", "refmap": "${mixingConfigRefMap}", "target": "@env(${mixinPluginPreInit.toBoolean() ? "PREINIT": "DEFAULT"})", "compatibilityLevel": "JAVA_8" } """ } } task relocateShadowJar(type: ConfigureShadowRelocation) { target = tasks.shadowJar prefix = modGroup + ".shadow" } shadowJar { if (remapStubs.toBoolean()) { dependsOn(removeStub) } project.configurations.shadeCompile.each { dep -> from(project.zipTree(dep)) { exclude 'META-INF', 'META-INF/**' } } manifest { attributes(getManifestAttributes()) } minimize() // This will only allow shading for actually used classes configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile] dependsOn(relocateShadowJar) } jar { if (remapStubs.toBoolean()) { dependsOn(removeStub) } project.configurations.shadeCompile.each { dep -> from(project.zipTree(dep)) { exclude 'META-INF', 'META-INF/**' } } manifest { attributes(getManifestAttributes()) } if(usesShadowedDependencies.toBoolean()) { dependsOn(shadowJar) enabled = false } } reobf { if(usesMixins.toBoolean()) { addExtraSrgFile mixinSrg } } if(usesMixins.toBoolean()) { tasks.compileJava { options.compilerArgs += [ '-Xlint:-processing', "-AreobfSrgFile=${srgFile}", "-AoutSrgFile=${mixinSrg}", "-AoutRefMapFile=${mixinRefMap}" ] } } runClient { def arguments = [] def jvmArguments = [] if(usesMixins.toBoolean() || hasMixinDeps.toBoolean()) { arguments += [ "--tweakClass", "org.spongepowered.asm.launch.MixinTweaker" ] jvmArguments += [ "-Dmixin.debug=true", "-Dmixin.debug.countInjections=true", "-Dmixin.debug.verbose=true", "-Dmixin.debug.export=true" ] } if(developmentEnvironmentUserName) { arguments += [ "--username", developmentEnvironmentUserName ] } args(arguments) jvmArgs(jvmArguments) } runServer { def arguments = [] def jvmArguments = [] if (usesMixins.toBoolean() || hasMixinDeps.toBoolean()) { arguments += [ "--tweakClass", "org.spongepowered.asm.launch.MixinTweaker" ] jvmArguments += [ "-Dmixin.debug=true", "-Dmixin.debug.countInjections=true", "-Dmixin.debug.verbose=true", "-Dmixin.debug.export=true" ] } args(arguments) jvmArgs(jvmArguments) } tasks.withType(JavaExec).configureEach { javaLauncher.set( javaToolchains.launcherFor { languageVersion = projectJavaVersion } ) } processResources { // this will ensure that this task is redone when the versions change. inputs.property "version", project.version inputs.property "mcversion", project.minecraft.version // replace stuff in mcmod.info, nothing else from(sourceSets.main.resources.srcDirs) { include 'mcmod.info' // replace modVersion and minecraftVersion expand "minecraftVersion": project.minecraft.version, "modVersion": modVersion, "modId": modId, "modName": modName } if(usesMixins.toBoolean()) { from mixinRefMap } // copy everything else that's not the mcmod.info from(sourceSets.main.resources.srcDirs) { exclude 'mcmod.info' } } 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()) { String[] configs = []; if (!mixinPlugin.isEmpty()) { configs += ["mixins.${modId}.json"]; } if (!mixinConfigs.isEmpty()) { configs += [mixinConfigs]; } manifestAttributes += [ "TweakClass" : "org.spongepowered.asm.launch.MixinTweaker", "MixinConfigs" : String.join(",", configs), "ForceLoadAsMod" : !containsMixinsAndOrCoreModOnly.toBoolean() ] } return manifestAttributes } task sourcesJar(type: Jar) { from (sourceSets.main.allSource) from (file("$projectDir/LICENSE")) getArchiveClassifier().set('sources') } task shadowDevJar(type: ShadowJar) { if (remapStubs.toBoolean()) { dependsOn(removeStub) } project.configurations.shadeCompile.each { dep -> from(project.zipTree(dep)) { exclude 'META-INF', 'META-INF/**' } } from sourceSets.main.output getArchiveClassifier().set("dev") manifest { attributes(getManifestAttributes()) } minimize() // This will only allow shading for actually used classes configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile] } task relocateShadowDevJar(type: ConfigureShadowRelocation) { target = tasks.shadowDevJar prefix = modGroup + ".shadow" } task circularResolverJar(type: Jar) { dependsOn(relocateShadowDevJar) dependsOn(shadowDevJar) enabled = false } task devJar(type: Jar) { if (remapStubs.toBoolean()) { dependsOn(removeStub) } project.configurations.shadeCompile.each { dep -> from(project.zipTree(dep)) { exclude 'META-INF', 'META-INF/**' } } from sourceSets.main.output getArchiveClassifier().set("dev") manifest { attributes(getManifestAttributes()) } if(usesShadowedDependencies.toBoolean()) { dependsOn(circularResolverJar) enabled = false } } task apiJar(type: Jar) { from (sourceSets.main.allSource) { if (apiPackage) include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' if (apiPackages) apiPackages.tokenize(';').forEach { pkg -> include modGroup.toString().replaceAll("\\.", "/") + "/" + pkg.toString().replaceAll("\\.", "/") + '/**' } if (apiPackagesNoRecurse) apiPackagesNoRecurse.tokenize(';').forEach { pkg -> include modGroup.toString().replaceAll("\\.", "/") + "/" + pkg.toString().replaceAll("\\.", "/") + '/*' } } from (sourceSets.main.output) { if (apiPackage) include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' if (apiPackages) apiPackages.tokenize(';').forEach { pkg -> include modGroup.toString().replaceAll("\\.", "/") + "/" + pkg.toString().replaceAll("\\.", "/") + '/**' } if (apiPackagesNoRecurse) apiPackagesNoRecurse.tokenize(';').forEach { pkg -> include modGroup.toString().replaceAll("\\.", "/") + "/" + pkg.toString().replaceAll("\\.", "/") + '/*' } } from (sourceSets.main.resources.srcDirs) { include("LICENSE") } getArchiveClassifier().set('api') } task copySrgs(type: Copy, dependsOn: 'genSrgs') { from plugins.getPlugin('forge').delayedFile('{SRG_DIR}') include '**/*.srg' into layout.buildDirectory.file('srgs') } compileJava.dependsOn(copySrgs) artifacts { archives sourcesJar archives devJar if(apiPackage || apiPackages || apiPackagesNoRecurse) { archives apiJar } } // The gradle metadata includes all of the additional deps that we disabled from POM generation (including forgeBin with no groupID), // and isn't strictly needed with the POM so just disable it. tasks.withType(GenerateModuleMetadata) { enabled = false } // workaround variable hiding in pom processing def projectConfigs = project.configurations // publishing def getMavenSettingsCredentials = { String userHome = System.getProperty( "user.home" ); File mavenSettings = new File(userHome, ".m2/settings.xml") def xmlSlurper = new XmlSlurper() def output = xmlSlurper.parse(mavenSettings) return output."servers"."server" } def getCredentials = { String username = System.getenv("MAVEN_DEPLOY_USER") String password = System.getenv("MAVEN_DEPLOY_PASSWORD") if (username == null) { try { def entries = getMavenSettingsCredentials() for (entry in entries) { if (entry."id".text() == repositoryName) { return [username: entry.username.text(), password: entry.password.text()] } } } catch (Exception ignored){} return [username: "none", password: "none"] } else { return [username: username, password: password] } } //Publishing tasks.publish.dependsOn(build) publishing { publications { maven(MavenPublication) { from components.java if (usesShadowedDependencies.toBoolean()) { artifact source: shadowJar, classifier: "" } if (!project.hasProperty("noPublishedSources") || !noPublishedSources) { artifact source: sourcesJar, classifier: "sources" } artifact source: usesShadowedDependencies.toBoolean() ? shadowDevJar : devJar, classifier: "dev" if (apiPackage || apiPackages || apiPackagesNoRecurse) { artifact source: apiJar, classifier: "api" } groupId = mavenGroupId artifactId = mavenArtifactId + "-mc" + minecraftVersion version = modVersion // remove extra garbage from minecraft and minecraftDeps configuration pom.withXml { def badArtifacts = [:].withDefault {[] as Set} for (configuration in [projectConfigs.minecraft, projectConfigs.minecraftDeps]) { for (dependency in configuration.allDependencies) { badArtifacts[dependency.group == null ? "" : dependency.group] += dependency.name } } // example for specifying extra stuff to ignore // badArtifacts["org.example.group"] += "artifactName" Node pomNode = asNode() pomNode.dependencies.'*'.findAll() { badArtifacts[it.groupId.text()].contains(it.artifactId.text()) }.each() { it.parent().remove(it) } } } } repositories { if (repositoryURL.trim() != "") { maven { name = repositoryName url = repositoryURL def creds = getCredentials() credentials { username = creds?.username ?: "none" password = creds?.password ?: "none" } } } } } tasks.withType(PublishToMavenRepository) { task -> dependsOn("build") } publishToMavenLocal.dependsOn("build") if (project.changelog == "") { File changelogFile = new File(System.getenv("CHANGELOG_FILE") ?: "CHANGELOG.md") if (changelogFile.exists()) { project.changelog = changelogFile.getText("UTF-8") } else { project.changelog = "No changelog was provided." } } project.changelog = project.changelog.replace("{version}", modVersion) if (curseForgeProjectId != "" && System.getenv("CURSEFORGE_TOKEN") != null) { apply plugin: 'com.matthewprenger.cursegradle' curseforge { apiKey = System.getenv("CURSEFORGE_TOKEN") project { id = curseForgeProjectId changelogType = "markdown" changelog = project.changelog releaseType = modVersion.contains("-a") ? "alpha" : modVersion.contains("-b") ? "beta" : "release" addGameVersion project.minecraft.version addGameVersion "Forge" mainArtifact(jar) { displayName = "$modName $modVersion" } } options { javaIntegration = false forgeGradleIntegration = false } } if (curseForgeRelations.size() != 0) { String[] deps = curseForgeRelations.split(";") deps.each { dep -> if (dep.size() == 0) { return } String[] parts = dep.split(":") String type = parts[0] String name = parts[1] addCurseForgeRelation(type, name) } } if (usesMixins.toBoolean()) { addCurseForgeRelation("requiredDependency", "unimixins") } tasks.curseforge.dependsOn(build) tasks.publish.dependsOn(tasks.curseforge) } if (modrinthProjectId != "" && System.getenv("MODRINTH_TOKEN") != null) { apply plugin: 'com.modrinth.minotaur' modrinth { token = System.getenv("MODRINTH_TOKEN") projectId = modrinthProjectId versionNumber = modVersion versionType = modVersion.contains("-a") ? "alpha" : modVersion.contains("-b") ? "beta" : "release" changelog = project.changelog uploadFile = jar gameVersions = [project.minecraft.version] loaders = ["forge"] } if (modrinthDependencies.size() != 0) { String[] deps = modrinthDependencies.split(";") deps.each { dep -> if (dep.size() == 0) { return } String[] parts = dep.split(":") String[] qual = parts[0].split("-") String scope = qual[0] String type = qual[1] String name = parts[1] addModrinthDep(scope, type, name) } } if (usesMixins.toBoolean()) { addModrinthDep("required", "project", "ghjoiQAl") } tasks.modrinth.dependsOn(build) tasks.publish.dependsOn(tasks.modrinth) } def addModrinthDep(scope, type, 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(type, 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 task updateBuildScript { doLast { if (performBuildScriptUpdate(projectDir.toString())) return print("Build script already up-to-date!") } } if (!project.getGradle().startParameter.isOffline() && !skipBuildScriptUpdateCheck.toBoolean() && isNewBuildScriptVersionAvailable(projectDir.toString())) { if (autoUpdateBuildScript.toBoolean()) { performBuildScriptUpdate(projectDir.toString()) } else { out.style(Style.SuccessHeader).println("Build script update available! Run 'gradle updateBuildScript'") } } static URL availableBuildScriptUrl() { new URL("https://raw.githubusercontent.com/FalsePattern/ExampleMod1.7.10/main/build.gradle") } boolean performBuildScriptUpdate(String projectDir) { if (isNewBuildScriptVersionAvailable(projectDir)) { def buildscriptFile = getFile("build.gradle") availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } } out.println("Build script updated. Please REIMPORT the project or RESTART your IDE!") return true } return false } boolean isNewBuildScriptVersionAvailable(String projectDir) { 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 "" } configure(updateBuildScript) { group = 'forgegradle' description = 'Updates the build script to the latest version' } // Parameter Deobfuscation task deobfParams { doLast { String mcpDir = "$project.gradle.gradleUserHomeDir/caches/minecraft/de/oceanlabs/mcp/mcp_$mappingsChannel/$mappingsVersion" String mcpZIP = "$mcpDir/mcp_$mappingsChannel-$mappingsVersion-${minecraftVersion}.zip" String paramsCSV = "$mcpDir/params.csv" download.run { src "https://maven.minecraftforge.net/de/oceanlabs/mcp/mcp_$mappingsChannel/$mappingsVersion-$minecraftVersion/mcp_$mappingsChannel-$mappingsVersion-${minecraftVersion}.zip" dest mcpZIP overwrite false } if(!file(paramsCSV).exists()) { println("Extracting MCP archive ...") unzip(mcpZIP, mcpDir) } println("Parsing params.csv ...") Map 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 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 } // Credit: bitsnaps (https://gist.github.com/bitsnaps/00947f2dce66f4bbdabc67d7e7b33681) static unzip(String zipFileName, String outputDir) { byte[] buffer = new byte[16384] ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFileName)) ZipEntry zipEntry = zis.getNextEntry() while (zipEntry != null) { File newFile = new File(outputDir + File.separator, zipEntry.name) if (zipEntry.isDirectory()) { if (!newFile.isDirectory() && !newFile.mkdirs()) { throw new IOException("Failed to create directory $newFile") } } else { // fix for Windows-created archives File parent = newFile.parentFile if (!parent.isDirectory() && !parent.mkdirs()) { throw new IOException("Failed to create directory $parent") } // write file content FileOutputStream fos = new FileOutputStream(newFile) int len = 0 while ((len = zis.read(buffer)) > 0) { fos.write(buffer, 0, len) } fos.close() } zipEntry = zis.getNextEntry() } zis.closeEntry() zis.close() } configure(deobfParams) { group = 'forgegradle' description = 'Rename all obfuscated parameter names inherited from Minecraft classes' } tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } // Dependency Deobfuscation def deobfMaven(mavenDep) { throw new GradleException("deobfMaven(mavenDep) is deprecated. " + "You must use the new deobfMaven(repoURL, mavenDep) method instead." + "The old method broke the buildscript when used.") } 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 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 e) { return deobf(sourceURL, "deobf/${sourceURL.hashCode()}") } } // 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 bon2Dir = "$cacheDir/forge_gradle/deobf" String bon2File = "$bon2Dir/BON2-${bon2Version}.jar" String obfFile = "$cacheDir/modules-2/files-2.1/${fileName}.jar" String deobfFile = "$cacheDir/modules-2/files-2.1/${fileName}-deobf.jar" if(file(deobfFile).exists()) { return files(deobfFile) } String mappingsVer if(remoteMappings) { String id = "${forgeVersion.split("\\.")[3]}-$minecraftVersion" String mappingsZIP = "$cacheDir/forge_gradle/maven_downloader/de/oceanlabs/mcp/mcp_snapshot_nodoc/$id/mcp_snapshot_nodoc-${id}.zip" zipMappings(mappingsZIP, remoteMappings, bon2Dir) mappingsVer = "snapshot_$id" } else { mappingsVer = "${mappingsChannel}_$mappingsVersion" } download.run { src "https://github.com/FalsePattern/ExampleMod1.7.10/raw/main/blobs/BON2-2.5.1.jar" dest bon2File quiet true overwrite false } download.run { src sourceURL dest obfFile quiet true overwrite false } exec { commandLine Paths.get(System.getProperty("java.home"), "bin", "java").toAbsolutePath().toString(), '-jar', bon2File, '--inputJar', obfFile, '--outputJar', deobfFile, '--mcVer', minecraftVersion, '--mappingsVer', mappingsVer, '--notch' workingDir bon2Dir standardOutput = new FileOutputStream("${deobfFile}.log") } return files(deobfFile) } def zipMappings(String zipPath, String url, String bon2Dir) { File zipFile = new File(zipPath) if(zipFile.exists()) { return } String fieldsCache = "$bon2Dir/data/fields.csv" String methodsCache = "$bon2Dir/data/methods.csv" download.run { src "${url}fields.csv" dest fieldsCache quiet true } download.run { src "${url}methods.csv" dest methodsCache quiet true } zipFile.getParentFile().mkdirs() ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile)) zos.putNextEntry(new ZipEntry("fields.csv")) Files.copy(Paths.get(fieldsCache), zos) zos.closeEntry() zos.putNextEntry(new ZipEntry("methods.csv")) Files.copy(Paths.get(methodsCache), zos) zos.closeEntry() zos.close() } // 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/FalsePattern/ExampleMod1.7.10/blob/main/gradle.properties") } } def propertyDefaultIfUnset(String propertyName, defaultValue) { if (!project.hasProperty(propertyName)) { System.err.println("Your gradle.properties is missing the $propertyName entry. It has been automatically set to \"$defaultValue\" as fallback. You can find all properties and their description here: https://github.com/FalsePattern/ExampleMod1.7.10/blob/main/gradle.properties") } if (!project.hasProperty(propertyName) || project.property(propertyName) == "") { project.ext.setProperty(propertyName, defaultValue) } } def getFile(String relativePath) { return new File(projectDir, relativePath) } if(file("addon_final.gradle").exists()) { apply from: "addon_final.gradle" }