diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4fc7603 --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### IntelliJ IDEA ### +.idea + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5378f70..a1e3956 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,9 +1,17 @@ +variables: + GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.jvmargs=-Xmx2G" + +before_script: + - export GRADLE_USER_HOME=`pwd`/.gradle + pages: + image: gradle:alpine stage: deploy script: - - shopt -s extglob + - gradle publish -Pmaven="$CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/maven" - mkdir public - - cp -r ./!(public) public + - cp ci/* public + - cp -r legacy/* public artifacts: paths: - public diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..070cb97 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,2 @@ +group = "io.gitlab.jfronny" +version = "1.0-SNAPSHOT" \ No newline at end of file diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 0000000..ac9bd54 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + `kotlin-dsl` +} + +repositories { + mavenCentral() + gradlePluginPortal() +} + +dependencies { + implementation("org.gradle.kotlin:gradle-kotlin-dsl-plugins:2.3.3") +} \ No newline at end of file diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts new file mode 100644 index 0000000..3331944 --- /dev/null +++ b/buildSrc/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name="scripts-conventions" \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/jf.plugin-conventions.gradle.kts b/buildSrc/src/main/kotlin/jf.plugin-conventions.gradle.kts new file mode 100644 index 0000000..a902f9c --- /dev/null +++ b/buildSrc/src/main/kotlin/jf.plugin-conventions.gradle.kts @@ -0,0 +1,40 @@ +plugins { + `java-gradle-plugin` + id("org.gradle.kotlin.kotlin-dsl") + `maven-publish` +} + +group = rootProject.group +version = rootProject.version + +repositories { + mavenCentral() + gradlePluginPortal() + maven { + name = "Fabric" + url = uri("https://maven.fabricmc.net/") + } + maven { + name = "CurseGradle" + url = uri("https://gitlab.com/api/v4/projects/32776914/packages/maven") + } +} + +publishing { + repositories { + if (project.hasProperty("maven")) { + maven(project.property("maven") as String) { + name = "dynamic" + + credentials(HttpHeaderCredentials::class) { + name = "Job-Token" + value = System.getenv()["CI_JOB_TOKEN"] + } + authentication { + create("header") + } + } + } + mavenLocal() + } +} \ No newline at end of file diff --git a/docs.yml b/ci/docs.yml similarity index 100% rename from docs.yml rename to ci/docs.yml diff --git a/jfmod.yml b/ci/jfmod.yml similarity index 100% rename from jfmod.yml rename to ci/jfmod.yml diff --git a/convention/build.gradle.kts b/convention/build.gradle.kts new file mode 100644 index 0000000..4e9d7d6 --- /dev/null +++ b/convention/build.gradle.kts @@ -0,0 +1,7 @@ +plugins { + id("jf.plugin-conventions") +} + +dependencies { + implementation("org.eclipse.jgit:org.eclipse.jgit:[6.0, 7.0)") +} \ No newline at end of file diff --git a/convention/src/main/kotlin/io/gitlab/jfronny/convention/VersionType.kt b/convention/src/main/kotlin/io/gitlab/jfronny/convention/VersionType.kt new file mode 100644 index 0000000..774ba56 --- /dev/null +++ b/convention/src/main/kotlin/io/gitlab/jfronny/convention/VersionType.kt @@ -0,0 +1,7 @@ +package io.gitlab.jfronny.convention + +enum class VersionType(val displayName: String, val curseforgeName: String, val modrinthName: String) { + RELEASE("Release", "release", "release"), + BETA("Beta", "beta", "beta"), + ALPHA("Alpha", "alpha", "alpha"); +} \ No newline at end of file diff --git a/convention/src/main/kotlin/io/gitlab/jfronny/convention/ext/JGitExt.kt b/convention/src/main/kotlin/io/gitlab/jfronny/convention/ext/JGitExt.kt new file mode 100644 index 0000000..b9e643e --- /dev/null +++ b/convention/src/main/kotlin/io/gitlab/jfronny/convention/ext/JGitExt.kt @@ -0,0 +1,87 @@ +package io.gitlab.jfronny.convention.ext + +import org.eclipse.jgit.api.Git +import org.eclipse.jgit.errors.IncorrectObjectTypeException +import org.eclipse.jgit.lib.AnyObjectId +import org.eclipse.jgit.lib.Constants +import org.eclipse.jgit.lib.ObjectId +import org.eclipse.jgit.lib.PersonIdent +import org.eclipse.jgit.lib.Ref +import org.eclipse.jgit.lib.Repository +import org.eclipse.jgit.revwalk.RevCommit +import org.eclipse.jgit.revwalk.RevTag +import org.eclipse.jgit.revwalk.RevWalk +import java.time.Instant +import java.time.ZoneOffset +import java.time.ZonedDateTime + +fun Git.log(since: AnyObjectId? = null, until: AnyObjectId? = null): List { + var command = this.log() + if (since != null) command = command.not(since) + if (until != null) command = command.add(until) + return command.call().map { it.resolve(repository) } +} + +fun Git.getTags(): List = repository.refDatabase.getRefsByPrefix(Constants.R_TAGS) + .map { it.resolveTag(repository) } + .sortedByDescending { it.dateTime } + +fun Ref.resolveTag(repo: Repository): Tag = RevWalk(repo).use { walk -> + val rev = try { + walk.parseTag(objectId) + } catch (e: IncorrectObjectTypeException) { + // Lightweight (unannotated) tag + // Copy information from commit + val target = walk.parseCommit(objectId).resolve(repo) + return Tag(objectId, null, name, target, target.author, target.fullMessage, target.shortMessage, target.dateTime) + } + walk.parseBody(rev) + walk.parseBody(rev.`object`) + val target = walk.peel(rev) + walk.parseBody(target) + return rev.resolve((target as RevCommit).resolve(repo)) +} + +fun RevTag.resolve(commit: Commit): Tag { + val ident = taggerIdent + return Tag( + id, + this, + name, + commit, + Person(ident, ident.name, ident.emailAddress), + fullMessage, + shortMessage, + ZonedDateTime.ofInstant( + ident.`when`.toInstant(), + ident.timeZone?.toZoneId() ?: ZoneOffset.UTC + ) + ) +} + +fun RevCommit.resolve(repo: Repository): Commit = Commit( + this, + ObjectId.toString(this), + try { + repo.newObjectReader().use { reader -> reader.abbreviate(this).name() } + } catch (e: Exception) { + Exception("Could not abbreviate $name", e).printStackTrace() + null + }, + Person(committerIdent, committerIdent.name, committerIdent.emailAddress), + Person(authorIdent, authorIdent.name, authorIdent.emailAddress), + ZonedDateTime.ofInstant( + Instant.ofEpochSecond(commitTime.toLong()), + committerIdent.timeZone?.toZoneId() ?: ZoneOffset.UTC + ), + fullMessage, + shortMessage, + parents.map { ObjectId.toString(it) } +) + +data class Tag(val id: ObjectId, val original: RevTag?, val fullName: String, val commit: Commit?, val tagger: Person?, val fullMessage: String?, val shortMessage: String?, val dateTime: ZonedDateTime?) { + val name: String + get() = Repository.shortenRefName(fullName) +} +data class Commit(val original: RevCommit, val id: String, val abbreviatedId: String?, val committer: Person, val author: Person, val dateTime: ZonedDateTime, val fullMessage: String, val shortMessage: String, val parentIds: List) +data class Person(val original: PersonIdent, val name: String, val emailAddress: String) \ No newline at end of file diff --git a/convention/src/main/kotlin/io/gitlab/jfronny/convention/ext/SharedProps.kt b/convention/src/main/kotlin/io/gitlab/jfronny/convention/ext/SharedProps.kt new file mode 100644 index 0000000..1a40594 --- /dev/null +++ b/convention/src/main/kotlin/io/gitlab/jfronny/convention/ext/SharedProps.kt @@ -0,0 +1,26 @@ +package io.gitlab.jfronny.convention.ext + +import io.gitlab.jfronny.convention.VersionType +import org.gradle.api.DefaultTask +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.tasks.TaskContainer +import org.gradle.kotlin.dsl.extra +import org.gradle.kotlin.dsl.named + +var Project.versionS: String + get() = version.toString() + set(value) { + version = value + } + +var Project.versionType: VersionType + get() = if (extra.has("io.gitlab.jfronny.scripts.getVersionType")) extra["io.gitlab.jfronny.scripts.getVersionType"] as VersionType else VersionType.RELEASE + set(value) = extra.set("io.gitlab.jfronny.scripts.getVersionType", value) + +var Project.changelog: String + get() = if (extra.has("io.gitlab.jfronny.scripts.getChangelog")) extra["io.gitlab.jfronny.scripts.getChangelog"].toString() else "" + set(value) = extra.set("io.gitlab.jfronny.scripts.getChangelog", value) + +val TaskContainer.deployDebug: Task get() = findByName("deployDebug") ?: register("deployDebug").get().dependsOn(named("build").get()) +val TaskContainer.deployRelease: Task get() = findByName("deployRelease") ?: register("deployRelease").get().dependsOn(deployDebug) \ No newline at end of file diff --git a/convention/src/main/kotlin/jf.autoversion.gradle.kts b/convention/src/main/kotlin/jf.autoversion.gradle.kts new file mode 100644 index 0000000..97bb965 --- /dev/null +++ b/convention/src/main/kotlin/jf.autoversion.gradle.kts @@ -0,0 +1,45 @@ +import io.gitlab.jfronny.convention.* +import io.gitlab.jfronny.convention.ext.* +import org.eclipse.jgit.api.Git +import java.awt.Toolkit +import java.awt.datatransfer.StringSelection + +versionS = "0.0.0+nogit" +versionType = VersionType.ALPHA +if (File(projectDir, ".git").exists()) { + Git.open(projectDir).use { git -> + versionS = "0.0.0+notag" + val tags: List = git.getTags() + if (tags.isNotEmpty()) { + if (tags[0].fullMessage != null) changelog += "${tags[0].fullMessage}\n" + versionS = tags[0].name + val vt = when(versionS[0]) { + 'v' -> VersionType.RELEASE + 'b' -> VersionType.BETA + 'a' -> VersionType.ALPHA + else -> null + } + versionType = vt ?: VersionType.RELEASE + if (vt != null) versionS = versionS.substring(1) + changelog += "Commits in $versionType $versionS:\n" + changelog += git.log(if (tags.size >= 2) tags[1].id else null, tags[0].id) + .reversed() + .joinToString("\n") { "- ${it.shortMessage}" } + } + } +} +if (changelog == "") changelog = "No io.gitlab.jfronny.scripts.getChangelog" + +val timestamp: Long = if (project.hasProperty("timestamp")) "${project.property("timestamp")}".toLong() +else (System.currentTimeMillis() / 1000L) + +if (project.hasProperty("release")) versionS += "-$timestamp" + +println(changelog) + +tasks.register("copyVersionNumber") { + doLast { + Toolkit.getDefaultToolkit().systemClipboard.setContents(StringSelection(versionS), null) + println("Copied version number: $versionS") + } +} diff --git a/convention/src/main/kotlin/jf.maven-publish.gradle.kts b/convention/src/main/kotlin/jf.maven-publish.gradle.kts new file mode 100644 index 0000000..13d05d8 --- /dev/null +++ b/convention/src/main/kotlin/jf.maven-publish.gradle.kts @@ -0,0 +1,24 @@ +plugins { + `maven-publish` +} + +publishing { + repositories { + mavenLocal() + + if (project.hasProperty("maven")) { + maven { + url = uri(project.property("maven").toString()) + name = "dynamic" + + credentials(HttpHeaderCredentials::class) { + name = "Job-Token" + value = System.getenv()["CI_JOB_TOKEN"] + } + authentication { + create("header") + } + } + } + } +} \ No newline at end of file diff --git a/jfmod/build.gradle.kts b/jfmod/build.gradle.kts new file mode 100644 index 0000000..863ad60 --- /dev/null +++ b/jfmod/build.gradle.kts @@ -0,0 +1,9 @@ +plugins { + id("jf.plugin-conventions") +} + +dependencies { + api(project(":lom")) + implementation("com.modrinth.minotaur:Minotaur:2.3.1") + implementation("io.gitlab.jfronny:CurseGradle:1.4.0-1642087331626") +} diff --git a/jfmod/src/main/kotlin/io/gitlab/jfronny/jfmod/ext/CurseGradleExt.kt b/jfmod/src/main/kotlin/io/gitlab/jfronny/jfmod/ext/CurseGradleExt.kt new file mode 100644 index 0000000..6a81dcc --- /dev/null +++ b/jfmod/src/main/kotlin/io/gitlab/jfronny/jfmod/ext/CurseGradleExt.kt @@ -0,0 +1,21 @@ +package io.gitlab.jfronny.jfmod.ext + +import com.matthewprenger.cursegradle.CurseExtension +import com.matthewprenger.cursegradle.CurseProject +import com.matthewprenger.cursegradle.CurseRelation +import com.matthewprenger.cursegradle.Options +import org.gradle.api.Action +import org.gradle.api.DefaultTask +import org.gradle.api.Project +import org.gradle.api.tasks.TaskContainer +import org.gradle.api.tasks.TaskProvider +import org.gradle.kotlin.dsl.closureOf +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.named + +val TaskContainer.curseforge: TaskProvider get() = named("curseforge") + +fun Project.curseforge(configure: Action) = extensions.configure { configure.execute(this) } +fun CurseExtension.options(configure: Action) = options(closureOf { configure.execute(this) }) +fun CurseExtension.project(configure: Action) = project(closureOf { configure.execute(this) }) +fun CurseProject.relations(configure: Action) = relations(closureOf { configure.execute(this) }) \ No newline at end of file diff --git a/jfmod/src/main/kotlin/jfmod.curseforge.gradle.kts b/jfmod/src/main/kotlin/jfmod.curseforge.gradle.kts new file mode 100644 index 0000000..1f2a5c5 --- /dev/null +++ b/jfmod/src/main/kotlin/jfmod.curseforge.gradle.kts @@ -0,0 +1,40 @@ +import io.gitlab.jfronny.convention.ext.* +import io.gitlab.jfronny.jfmod.ext.* +import io.gitlab.jfronny.lom.ext.* + +plugins { + id("jfmod") + id("com.matthewprenger.cursegradle") +} + +curseforge { + if (System.getenv().containsKey("CURSEFORGE_API_TOKEN")) apiKey = System.getenv()["CURSEFORGE_API_TOKEN"] + else println("No CURSEFORGE_API_TOKEN specified") + project { + id = prop("curseforge_id") + releaseType = versionType.curseforgeName + addGameVersion("Fabric") + addGameVersion(lom.minecraftVersion.get()) + changelog = project.changelog + mainArtifact(tasks.remapJar.get().archiveFile.get()) + mainArtifact.displayName = "[${lom.minecraftVersion.get()}] $versionS" + relations { + prop("curseforge_required_dependencies", "") + .split(", ", ",") + .filter { it.isNotBlank() } + .forEach { requiredDependency(it) } + prop("curseforge_optional_dependencies", "") + .split(", ", ",") + .filter { it.isNotBlank() } + .forEach { optionalDependency(it) } + } + afterEvaluate { + uploadTask.dependsOn(tasks.build) + } + } + options { + forgeGradleIntegration = false + } +} + +tasks.deployRelease.dependsOn(tasks.curseforge) diff --git a/jfmod/src/main/kotlin/jfmod.gradle.kts b/jfmod/src/main/kotlin/jfmod.gradle.kts new file mode 100644 index 0000000..ba48c5b --- /dev/null +++ b/jfmod/src/main/kotlin/jfmod.gradle.kts @@ -0,0 +1,103 @@ +import io.gitlab.jfronny.convention.ext.* +import io.gitlab.jfronny.lom.ext.* + +plugins { + id("jf.autoversion") + id("jf.maven-publish") + id("lom") +} + +//TODO test libjf-config-compiler-plugin integration +if (project.hasProperty("libjf_version")) { + buildscript { + repositories { + maven { + name = "JF Commons" + url = uri("https://gitlab.com/api/v4/projects/35745143/packages/maven") + } + maven { + name = "LibJF" + url = uri("https://gitlab.com/api/v4/projects/25805200/packages/maven") + } + } + + dependencies { + classpath("io.gitlab.jfronny.libjf:libjf-config-compiler-plugin:${prop("libjf_version")}") + } + } +} + +val devOnlyModules by extra(prop("dev_only_module", "").split(", ", ",").filter { it.isNotBlank() }) +val nonModSubprojects by extra(prop("non_mod_project", "").split(", ", ",").filter { it.isNotBlank() }) +val self = project + +allprojects { + if (name in nonModSubprojects) return@allprojects + + group = self.group + version = self.version + + apply(plugin = "jf.maven-publish") + apply(plugin = "lom") + if (self.hasProperty("libjf_version")) apply(plugin = "io.gitlab.jfronny.libjf.libjf-config-compiler-plugin") + + base { + archivesName.set(prop("archives_base_name", archivesName.get())) + } + + lom { + minecraftVersion.set(prop("minecraft_version")) + loaderVersion.set(prop("loader_version")) + if (hasProperty("yarn_mappings")) yarn(prop("yarn_mappings")) + else mojmap() + } + + afterEvaluate { + self.allprojects.forEach { sub -> + if (sub != this && sub.name !in nonModSubprojects) { + loom { + mods { + register(sub.name) { + sourceSet(sub.sourceSets.main) + sourceSet(sub.sourceSets.client) + } + register("${sub.name}-testmod") { + sourceSet(sub.sourceSets.testmod) + } + } + } + } + } + } +} + +subprojects { + if (name in nonModSubprojects) return@subprojects + + self.tasks.deployDebug.dependsOn(tasks.deployDebug) + self.tasks.deployRelease.dependsOn(tasks.deployRelease) + + tasks.named("javadoc").get().enabled = false + + afterEvaluate { + dependencies { + testmodImplementation(sourceSets.main.output) + } + + tasks.genClientOnlySources.enabled = false + tasks.genCommonSources.enabled = false + tasks.unpickClientOnlyJar.enabled = false + tasks.unpickCommonJar.enabled = false + + rootProject.dependencies { + api(project(mapOf("path" to project.path, "configuration" to "shadow"))) + clientImplementation(sourceSets.client.output) + testmodImplementation(sourceSets.testmod.output) + + if (name !in devOnlyModules) include(project) + } + } +} + +if (hasProperty("curseforge_id")) apply(plugin = "jfmod.curseforge") +if (hasProperty("modrinth_id")) apply(plugin = "jfmod.modrinth") \ No newline at end of file diff --git a/jfmod/src/main/kotlin/jfmod.modrinth.gradle.kts b/jfmod/src/main/kotlin/jfmod.modrinth.gradle.kts new file mode 100644 index 0000000..04395fa --- /dev/null +++ b/jfmod/src/main/kotlin/jfmod.modrinth.gradle.kts @@ -0,0 +1,40 @@ +import io.gitlab.jfronny.convention.ext.* +import io.gitlab.jfronny.lom.ext.* + +plugins { + id("jfmod") + id("com.modrinth.minotaur") +} + +val readmeFile = file("README.md") + +modrinth { + token.set(System.getenv()["MODRINTH_API_TOKEN"]) + projectId.set(prop("modrinth_id")) + versionName.set("[${lom.minecraftVersion.get()}] $versionS") + versionType.set(project.versionType.modrinthName) + changelog.set(project.changelog) + uploadFile.set(tasks.remapJar.get()) + gameVersions.add(lom.minecraftVersion.get()) + loaders.add("fabric") + prop("modrinth_required_dependencies", "") + .split(", ", ",") + .filter { it.isNotBlank() } + .forEach { required.project(it) } + prop("modrinth_optional_dependencies", "") + .split(", ", ",") + .filter { it.isNotBlank() } + .forEach { optional.project(it) } + if (readmeFile.exists()) { + syncBodyFrom.set( + """${readmeFile.readText()} + +[![Contact](https://img.shields.io/badge/-Contact-informational)](https://jfronny.gitlab.io/contact.html)""" + ) + } +} + +tasks.deployRelease.dependsOn(tasks.modrinth) +if (readmeFile.exists()) { + tasks.deployRelease.dependsOn(tasks.modrinthSyncBody) +} \ No newline at end of file diff --git a/gradle/v1.gradle b/legacy/gradle/v1.gradle similarity index 99% rename from gradle/v1.gradle rename to legacy/gradle/v1.gradle index f2a0329..f87bd8a 100644 --- a/gradle/v1.gradle +++ b/legacy/gradle/v1.gradle @@ -243,7 +243,7 @@ allprojects { } build.dependsOn remapMavenJar - task testmodJar(type: Jar) { //TODO include deps + task testmodJar(type: Jar) { from sourceSets.testmod.output destinationDirectory = new File(project.buildDir, "devlibs") archiveClassifier = "testmod" diff --git a/gradle/v2.gradle b/legacy/gradle/v2.gradle similarity index 100% rename from gradle/v2.gradle rename to legacy/gradle/v2.gradle diff --git a/jfmod.gradle b/legacy/jfmod.gradle similarity index 100% rename from jfmod.gradle rename to legacy/jfmod.gradle diff --git a/lom/build.gradle.kts b/lom/build.gradle.kts new file mode 100644 index 0000000..87249b6 --- /dev/null +++ b/lom/build.gradle.kts @@ -0,0 +1,19 @@ +plugins { + id("jf.plugin-conventions") +} + +gradlePlugin { + // Define the plugin + plugins { + create("lom") { + id = "lom" + implementationClass = "io.gitlab.jfronny.lom.LomPlugin" + } + } +} + +dependencies { + api(project(":convention")) + api("net.fabricmc:fabric-loom:1.0-SNAPSHOT") + api("gradle.plugin.com.github.johnrengelman:shadow:7.1.2") +} \ No newline at end of file diff --git a/lom/src/main/kotlin/io/gitlab/jfronny/lom/LomExtension.kt b/lom/src/main/kotlin/io/gitlab/jfronny/lom/LomExtension.kt new file mode 100644 index 0000000..6e67f9e --- /dev/null +++ b/lom/src/main/kotlin/io/gitlab/jfronny/lom/LomExtension.kt @@ -0,0 +1,27 @@ +package io.gitlab.jfronny.lom + +import net.fabricmc.loom.LoomGradleExtension +import org.gradle.api.Project +import org.gradle.api.provider.Property +import java.util.* + +interface LomExtension { + var yarnBuild: String? + + fun yarn(yarnBuild: String) { + this.yarnBuild = Objects.requireNonNull(yarnBuild) + } + + fun mojmap() { + yarnBuild = null + } + + val minecraftVersion: Property + val loaderVersion: Property + + companion object { + operator fun get(project: Project): LoomGradleExtension { + return project.extensions.getByName("lom") as LoomGradleExtension + } + } +} \ No newline at end of file diff --git a/lom/src/main/kotlin/io/gitlab/jfronny/lom/LomPlugin.kt b/lom/src/main/kotlin/io/gitlab/jfronny/lom/LomPlugin.kt new file mode 100644 index 0000000..6ec2358 --- /dev/null +++ b/lom/src/main/kotlin/io/gitlab/jfronny/lom/LomPlugin.kt @@ -0,0 +1,187 @@ +package io.gitlab.jfronny.lom + +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import io.gitlab.jfronny.convention.ext.deployDebug +import io.gitlab.jfronny.convention.ext.versionS +import io.gitlab.jfronny.lom.ext.* +import io.gitlab.jfronny.lom.ext.registering +import net.fabricmc.loom.task.RemapJarTask +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.publish.maven.MavenPublication +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 + +class LomPlugin : Plugin { + override fun apply(target: Project) { + target.applyLom() + } + + private fun Project.applyLom() { + val devlibs = File(project.buildDir, "devlibs") + val args = AfterEvaluateArgs(extensions.create("lom"), null, null) + + afterEvaluate { lomAfterEvaluate(args) } // Needs to be registered before loom to properly set things up + + apply(plugin = "idea") + apply(plugin = "java-library") + apply(plugin = "fabric-loom") + apply(plugin = "maven-publish") + apply(plugin = "com.github.johnrengelman.shadow") + + loom { + runtimeOnlyLog4j.set(true) + splitEnvironmentSourceSets() + + mods { + register(name) { + sourceSet(sourceSets.main) + sourceSet(sourceSets.client) + } + register("$name-testmod") { + sourceSet(sourceSets.testmod) + } + } + } + + sourceSets { + create("testmod") { + compileClasspath += sourceSets.main.compileClasspath + runtimeClasspath += sourceSets.main.runtimeClasspath + + compileClasspath += sourceSets.client.compileClasspath + runtimeClasspath += sourceSets.client.runtimeClasspath + } + } + + 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() + } + + configurations.create("dev") + tasks.jar.archiveClassifier.set("dev") + + val inputTask: Jar = tasks.findByName("injectCompiledConfig") as Jar? ?: tasks.jar + + val completeJar by tasks.registering(ShadowJar::class) { + dependsOn(inputTask) + configurations.clear() + configurations.add(project.configurations.shadow) + archiveClassifier.set("shadow") + destinationDirectory.set(devlibs) + } + args.completeJar = completeJar + + artifacts.add("dev", tasks.jar.archiveFile.get().asFile) { + type = "jar" + builtBy(tasks.jar) + } + + java { + withSourcesJar() + } + + tasks.withType() { + isPreserveFileTimestamps = false + isReproducibleFileOrder = false + } + + val remapMavenJar by tasks.registering(RemapJarTask::class) { + dependsOn(completeJar) + archiveFileName.set("$archiveBaseName-${project.versionS}-maven.jar") + addNestedDependencies.set(false) + } + args.remapMavenJar = remapMavenJar + tasks.assemble.dependsOn(remapMavenJar) + + val testmodJar by tasks.registering(Jar::class) { //TODO include deps + from(sourceSets.testmod.output) + destinationDirectory.set(devlibs) + archiveClassifier.set("testmod") + } + + val remapTestmodJar by tasks.registering(RemapJarTask::class) { + dependsOn(testmodJar) + inputFile.set(testmodJar.archiveFile) + archiveClassifier.set("testmod") + addNestedDependencies.set(false) + } + tasks.assemble.dependsOn(remapTestmodJar) + } + + private fun Project.lomAfterEvaluate(args: AfterEvaluateArgs) { + val extension = args.extension + val completeJar = args.completeJar!! + val remapMavenJar = args.remapMavenJar!! + + tasks.withType().configureEach { + options.encoding = "UTF-8" + options.release.set(17) + } + + dependencies { + minecraft("com.mojang:minecraft:${extension.minecraftVersion.get()}") + if (extension.yarnBuild != null) mappings("net.fabricmc:yarn:${extension.minecraftVersion.get()}+${extension.yarnBuild}:v2") + else loom.officialMojangMappings() + modImplementation("net.fabricmc:fabric-loader:${extension.loaderVersion.get()}") + + testmodImplementation(sourceSets.main.output) + testmodImplementation(sourceSets.client.output) + } + + tasks.remapJar { + dependsOn(completeJar) + + inputFile.set(completeJar.archiveFile) + archiveFileName.set("$archiveBaseName-${project.versionS}.jar") + } + + tasks.processResources { + filesMatching("fabric.mod.json") { + expand(mapOf("version" to project.versionS)) + } + } + + publishing { + publications { + create("mavenJava") { + artifact(remapMavenJar) { + builtBy(remapMavenJar) + } + + artifact(tasks.sourcesJar) { + builtBy(tasks.remapSourcesJar) + } + } + } + } + tasks.publish.dependsOn(tasks.build) + tasks.deployDebug.dependsOn(tasks.publish) + } + + private data class AfterEvaluateArgs(val extension: LomExtension, var completeJar: ShadowJar?, var remapMavenJar: RemapJarTask?) +} \ No newline at end of file diff --git a/lom/src/main/kotlin/io/gitlab/jfronny/lom/ext/GradleExt.kt b/lom/src/main/kotlin/io/gitlab/jfronny/lom/ext/GradleExt.kt new file mode 100644 index 0000000..a0c6579 --- /dev/null +++ b/lom/src/main/kotlin/io/gitlab/jfronny/lom/ext/GradleExt.kt @@ -0,0 +1,47 @@ +package io.gitlab.jfronny.lom.ext + +import org.gradle.api.Action +import org.gradle.api.DefaultTask +import org.gradle.api.PolymorphicDomainObjectContainer +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.api.publish.PublishingExtension +import org.gradle.api.tasks.SourceSetContainer +import org.gradle.api.tasks.TaskContainer +import org.gradle.api.tasks.bundling.Jar +import org.gradle.kotlin.dsl.named +import org.gradle.kotlin.dsl.support.delegates.ProjectDelegate +import org.gradle.language.jvm.tasks.ProcessResources +import kotlin.reflect.KClass +import kotlin.reflect.KProperty + +val Project.java: JavaPluginExtension get() = extensions.getByName("java") as JavaPluginExtension +fun Project.java(configure: Action) = extensions.configure("java", configure) +val Project.publishing: PublishingExtension get() = extensions.getByName("publishing") as PublishingExtension +fun Project.publishing(configure: Action) = extensions.configure("publishing", configure) + +val Project.sourceSets: SourceSetContainer get() = extensions.getByName("sourceSets") as SourceSetContainer +fun Project.sourceSets(configure: Action) = extensions.configure("sourceSets", configure) + +val TaskContainer.assemble: DefaultTask get() = named("assemble").get() +val TaskContainer.build: DefaultTask get() = named("build").get() +val TaskContainer.jar: Jar get() = named("jar").get() +val TaskContainer.sourcesJar: Jar get() = named("sourcesJar").get() +val TaskContainer.publish: Task get() = named("publish").get() +fun TaskContainer.processResources(configure: ProcessResources.() -> Unit) = named("processResources").configure(configure) + +fun , U : T> C.registering(type: KClass, action: U.() -> Unit): PDelegate = PDelegate(this, type.java, action) + +class PDelegate, U : T>(private val container: C, private val type: Class, private val action: U.() -> Unit) { + operator fun provideDelegate(thisRef: Any?, property: KProperty<*>): SDelegate = SDelegate(container.register(property.name, type, action).get()) +} + +class SDelegate(private val delegate: T) { + operator fun getValue(thisRef: Any?, property: KProperty<*>): T = delegate +} + +fun Project.prop(name: String, default: String? = null): String { + return if (default == null || hasProperty(name)) property(name).toString() + else default +} \ No newline at end of file diff --git a/lom/src/main/kotlin/io/gitlab/jfronny/lom/ext/LoomExt.kt b/lom/src/main/kotlin/io/gitlab/jfronny/lom/ext/LoomExt.kt new file mode 100644 index 0000000..f5d25f0 --- /dev/null +++ b/lom/src/main/kotlin/io/gitlab/jfronny/lom/ext/LoomExt.kt @@ -0,0 +1,38 @@ +package io.gitlab.jfronny.lom.ext + +import net.fabricmc.loom.api.LoomGradleExtensionAPI +import net.fabricmc.loom.task.GenerateSourcesTask +import net.fabricmc.loom.task.RemapJarTask +import net.fabricmc.loom.task.RemapSourcesJarTask +import net.fabricmc.loom.task.UnpickJarTask +import org.gradle.api.Action +import org.gradle.api.DefaultTask +import org.gradle.api.Project +import org.gradle.api.artifacts.dsl.DependencyHandler +import org.gradle.api.tasks.SourceSet +import org.gradle.api.tasks.SourceSetContainer +import org.gradle.api.tasks.TaskContainer +import org.gradle.kotlin.dsl.named + +val Project.loom: LoomGradleExtensionAPI get() = extensions.getByName("loom") as LoomGradleExtensionAPI +fun Project.loom(configure: Action) = extensions.configure("loom", configure) + +fun DependencyHandler.minecraft(dependencyNotation: Any) = add("minecraft", dependencyNotation) +fun DependencyHandler.mappings(dependencyNotation: Any) = add("mappings", dependencyNotation) +fun DependencyHandler.modImplementation(dependencyNotation: Any) = add("modImplementation", dependencyNotation) +fun DependencyHandler.testmodImplementation(dependencyNotation: Any) = add("testmodImplementation", dependencyNotation) +fun DependencyHandler.clientImplementation(dependencyNotation: Any) = add("clientImplementation", dependencyNotation) + +val SourceSetContainer.main: SourceSet get() = named("main").get() +fun SourceSetContainer.main(configure: Action) = configure.execute(this.main) +val SourceSetContainer.client: SourceSet get() = named("client").get() +fun SourceSetContainer.client(configure: Action) = configure.execute(this.client) +val SourceSetContainer.testmod: SourceSet get() = named("testmod").get() +fun SourceSetContainer.testmod(configure: Action) = configure.execute(this.testmod) + +fun TaskContainer.remapJar(configure: RemapJarTask.() -> Unit) = named("remapJar").configure(configure) +val TaskContainer.remapSourcesJar: RemapSourcesJarTask get() = named("remapSourcesJar").get() +val TaskContainer.genClientOnlySources: DefaultTask get() = named("genClientOnlySources").get() +val TaskContainer.genCommonSources: DefaultTask get() = named("genCommonSources").get() +val TaskContainer.unpickClientOnlyJar: UnpickJarTask get() = named("unpickClientOnlyJar").get() +val TaskContainer.unpickCommonJar: UnpickJarTask get() = named("unpickCommonJar").get() \ No newline at end of file diff --git a/lom/src/main/kotlin/io/gitlab/jfronny/lom/ext/ShadowExt.kt b/lom/src/main/kotlin/io/gitlab/jfronny/lom/ext/ShadowExt.kt new file mode 100644 index 0000000..dbcb82f --- /dev/null +++ b/lom/src/main/kotlin/io/gitlab/jfronny/lom/ext/ShadowExt.kt @@ -0,0 +1,6 @@ +package io.gitlab.jfronny.lom.ext + +import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.ConfigurationContainer + +val ConfigurationContainer.shadow: Configuration get() = named("shadow").get() \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..79d60d0 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,5 @@ +rootProject.name = "scripts" + +include("lom") +include("convention") +include("jfmod")