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 { name = "TerraformersMC" url = uri("https://maven.terraformersmc.com/") } maven { name = "LibJF" url = uri("https://gitlab.com/api/v4/projects/25805200/packages/maven") } maven { name = "JF Gson" url = uri("https://gitlab.com/api/v4/projects/35030495/packages/maven") } maven { name = "JF Commons" url = uri("https://gitlab.com/api/v4/projects/35745143/packages/maven") } maven { name = "JF FLoader" url = uri("https://gitlab.com/api/v4/projects/36014652/packages/maven") } mavenCentral() mavenLocal() } // Register common dependencies val args = extensions.create("lom") earlyAfterEvaluate { dependencies { minecraft("com.mojang:minecraft:${args.minecraftVersion.get()}") if (args.yarnBuild != null) mappings("net.fabricmc:yarn:${args.minecraftVersion.get()}+${args.yarnBuild}:v2") else loom.officialMojangMappings() modImplementation("net.fabricmc:fabric-loader:${args.loaderVersion.get()}") testmodImplementation(sourceSets.main.get().output) testmodImplementation(sourceSets.client.get().output) } } // Mark normal jars as -dev tasks.jar.get().archiveClassifier.set("dev") // Used for referencing the unremapped jars of other projects artifacts.add(configurations.create("dev").name, tasks.jar.get().archiveFile.get().asFile) { type = "jar" builtBy(tasks.jar.get()) } // configure the shadow task to not shadow by default and output to builds/devlibs tasks.shadowJar { val inputTask: Jar = tasks.findByName("injectCompiledConfig") as Jar? ?: tasks.jar.get() // get injectCompiledConfig task if present (-> LibJF) or use normal jar task dependsOn(inputTask) configurations.clear() from(project.configurations.shadow.get(), inputTask.archiveFile.get()) archiveClassifier.set("shadow") destinationDirectory.set(devlibs) } // 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.get()) inputFile.set(tasks.shadowJar.get().archiveFile.get()) archiveFileName.set("${archiveBaseName.get()}-${project.versionS}-maven.jar") addNestedDependencies.set(false) } tasks.assemble.get().dependsOn(remapMavenJar.get()) // configure remapJar to use the output of shadow tasks.remapJar { dependsOn(tasks.shadowJar.get()) inputFile.set(tasks.shadowJar.get().archiveFile.get()) 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.get(), tasks.sourcesJar.get())) } } } tasks.publish.get().dependsOn(tasks.build.get()) tasks.deployDebug.dependsOn(tasks.publish.get()) // 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.get()) inputFile.set(testmodJar.get().archiveFile.get()) archiveClassifier.set("testmod") // add nested jars from testmodInclude addNestedDependencies.set(true) nestedJars.setFrom(*testmodIncludeConfiguration.files.toTypedArray()) } tasks.assemble.get().dependsOn(remapTestmodJar.get()) } } 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.filter { it != prepareTask }.toTypedArray()) } } } }