import io.gitlab.jfronny.scripts.* import net.fabricmc.loom.task.PrepareJarRemapTask import net.fabricmc.loom.task.RemapJarTask import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.publish.tasks.GenerateModuleMetadata import org.gradle.api.tasks.bundling.AbstractArchiveTask import org.gradle.api.tasks.bundling.Jar import org.gradle.api.tasks.compile.JavaCompile import org.gradle.kotlin.dsl.* import java.io.File plugins { id("jf.earlyafterevaluate") idea `java-library` `maven-publish` id("fabric-loom") id("com.github.johnrengelman.shadow") } val devlibs = File(project.buildDir, "devlibs") // Configure loom for stricter dev env loom { runtimeOnlyLog4j.set(true) splitEnvironmentSourceSets() } // Create testmod source set with access to main and client classpaths sourceSets { create("testmod") { compileClasspath += sourceSets.main.get().compileClasspath runtimeClasspath += sourceSets.main.get().runtimeClasspath compileClasspath += sourceSets.client.get().compileClasspath runtimeClasspath += sourceSets.client.get().runtimeClasspath } } val hasTestmod = !sourceSets.testmod.get().resources.isEmpty // Class path groups (required to allow ultra early init) loom { mods { register(name) { sourceSet(sourceSets.main.get()) sourceSet(sourceSets.client.get()) } if (hasTestmod) { register("$name-testmod") { sourceSet(sourceSets.testmod.get()) } } } if (hasTestmod) { runs { create("testmodClient") { client() ideConfigGenerated(rootProject == project) name("Testmod Client") source(sourceSets.testmod.get()) } create("testmodServer") { server() ideConfigGenerated(rootProject == project) name("Testmod Server") source(sourceSets.testmod.get()) } } } } // Common repositories for mods repositories { maven("https://maven.terraformersmc.com/") { name = "TerraformersMC" } maven("https://maven.frohnmeyer-wds.de/artifacts") { name = "JFronny" } mavenCentral() mavenLocal() } // Register common dependencies val args = extensions.create("lom") earlyAfterEvaluate { args.check(this) dependencies { minecraft("com.mojang:minecraft:${args.minecraftVersion.get()}") if (args.yarnBuild.isPresent) mappings("net.fabricmc:yarn:${args.minecraftVersion.get()}+${args.yarnBuild.get()}:v2") else loom.officialMojangMappings() modImplementation("net.fabricmc:fabric-loader:${args.loaderVersion.get()}") testImplementation("net.fabricmc:fabric-loader-junit:${args.loaderVersion.get()}") testmodImplementation(sourceSets.main.get().output) testmodImplementation(sourceSets.client.get().output) } } tasks.test { useJUnitPlatform() } // Mark normal jars as -dev tasks.jar.get().archiveClassifier.set("dev") // configure the shadow task to not shadow by default and output to builds/devlibs tasks.shadowJar { // get injectCompiledConfig task if present (-> LibJF) or use normal jar task val inputTask = providers.provider { tasks.findByName("injectCompiledConfig") as Jar? }.orElse(tasks.jar) dependsOn(inputTask) configurations.clear() from(project.configurations.shadow, inputTask) archiveClassifier.set("shadow") destinationDirectory.set(devlibs) } // Used for referencing the unremapped jars of other projects artifacts.add(configurations.create("dev").name, tasks.shadowJar) { type = "jar" builtBy(tasks.shadowJar) } // generate sources jar to publish for better debugging with dependents java { withSourcesJar() } // attempt to allow reproducible builds by removing unneeded metadata from jars tasks.withType { isPreserveFileTimestamps = false isReproducibleFileOrder = false } // generate remapped jar without JiJ'd dependencies for maven publish val remapMavenJar by tasks.registering(RemapJarTask::class) { dependsOn(tasks.shadowJar) inputFile.set(tasks.shadowJar.get().archiveFile) archiveFileName.set("${archiveBaseName.get()}-${project.versionS}-maven.jar") addNestedDependencies.set(false) } tasks.assemble { dependsOn(remapMavenJar) } // configure remapJar to use the output of shadow tasks.remapJar { dependsOn(tasks.shadowJar) inputFile.set(tasks.shadowJar.get().archiveFile) archiveFileName.set("${archiveBaseName.get()}-${project.versionS}.jar") } // fill in mod version tasks.processResources { filesMatching("fabric.mod.json") { expand(mapOf("version" to project.versionS)) } } // publish sources jar and remapped jar without JiJ'd deps publishing { publications { create("lom") { from(components["java"]) setArtifacts(listOf(remapMavenJar, tasks.sourcesJar)) } } } tasks.publish { dependsOn(tasks.build) } tasks.deployDebug.dependsOn(tasks.publish) // create testmodInclude configuration val testmodIncludeConfiguration = configurations.create("testmodInclude") if (hasTestmod) { // generate jar from testmod source set val testmodJar by tasks.registering(Jar::class) { from(sourceSets.testmod.get().output) destinationDirectory.set(devlibs) archiveClassifier.set("testmod") } afterEvaluate { // remap configuration for outputting usable testmod jar val remapTestmodJar by tasks.registering(RemapJarTask::class) { dependsOn(testmodJar) inputFile.set(testmodJar.get().archiveFile) archiveClassifier.set("testmod") // add nested jars from testmodInclude addNestedDependencies.set(true) nestedJars.setFrom(*testmodIncludeConfiguration.files.toTypedArray()) } tasks.assemble { dependsOn(remapTestmodJar) } } } afterEvaluate { // from fabric-example-mod, enforces modern java tasks.withType().configureEach { options.encoding = "UTF-8" options.release.set(17) } // otherwise we can't easily overwrite the artifacts to publish while keeping dependency metadata tasks.withType { enabled = false } // Fix prepareRemapJar // Finds remapJar tasks and the corresponding prepareRemapJar tasks and ensures the dependencies of remapJar are run before prepareRemapJar // This ensures the input files exist when the task is run tasks.configureEach { if (this is RemapJarTask) { this.dependsOn.filterIsInstance().forEach { prepareTask -> prepareTask.dependsOn(*this.dependsOn.filterNot { it == prepareTask }.toTypedArray()) } } } }