diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ea5ab14..6177ae8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -50,12 +50,12 @@ jobs: with: name: build-fabric path: fabric/build/libs - - name: Capture Forge Artifacts + - name: Capture Neo Artifacts if: ${{ runner.os == 'Linux' && matrix.java == '17' }} # Only upload artifacts built from latest java on one OS uses: actions/upload-artifact@v4 with: - name: build-forge - path: forge/build/libs + name: build-neo + path: neoforge/build/libs - name: Capture Changelog if: ${{ runner.os == 'Linux' && matrix.java == '17' }} # Only upload artifacts built from latest java on one OS uses: actions/upload-artifact@v4 @@ -78,11 +78,11 @@ jobs: path: build/fabric pattern: build-fabric merge-multiple: true - - name: Download Forge artifacts + - name: Download Neo artifacts uses: actions/download-artifact@v4 with: - path: build/forge - pattern: build-forge + path: build/neo + pattern: build-neo merge-multiple: true - name: Download Changelog uses: actions/download-artifact@v4 @@ -102,9 +102,9 @@ jobs: path: "./gradle.properties" properties: "version enabledPlatforms minecraftVersion" - - name: Upload Forge Releases (Curse/Modrinth) - id: forge_release - if: contains(steps.properties.outputs.enabledPlatforms, 'forge') + - name: Upload Neo Releases (Curse/Modrinth) + id: neo_release + if: contains(steps.properties.outputs.enabledPlatforms, 'neoforge') uses: Kir-Antipov/mc-publish@v3.3.0 with: curseforge-id: ${{ vars.CURSE_ID }} @@ -114,7 +114,7 @@ jobs: modrinth-token: ${{ secrets.MODRINTH_TOKEN }} files: ./build/forge/!(*-@(dev|sources|dev-shadow)).jar - name: "AstralBot ${{ steps.properties.outputs.version }} Forge ${{ steps.properties.output.minecraftVersion }}" + name: "AstralBot ${{ steps.properties.outputs.version }} NeoForge ${{ steps.properties.output.minecraftVersion }}" version: ${{ steps.properties.outputs.version }} version-type: release changelog-file: build-changelog/prepared_changelog.md @@ -122,11 +122,9 @@ jobs: game-versions: ${{ steps.properties.outputs.minecraftVersion }} curseforge-dependencies: | - sqlite-jdbc(optional) kotlin-for-forge(required) forge-config-api-port-fabric(required) modrinth-dependencies: | - sqlite-jdbc(optional) kotlin-for-forge(required) forge-config-api-port(required) @@ -153,11 +151,7 @@ jobs: fabric-api(required) fabric-language-kotlin(required) forge-config-api-port-fabric(required) - sqlite-jdbc(optional) - ledger(optional) modrinth-dependencies: | fabric-api(required) fabric-language-kotlin(required) - forge-config-api-port(required) - sqlite-jdbc(optional) - ledger(optional) \ No newline at end of file + forge-config-api-port(required) \ No newline at end of file diff --git a/Changelog.md b/Changelog.md index a0c2f6c..e9a7112 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,8 @@ +# 1.4.0 +- Port to 1.20.4 and NeoForge +- Removed Forge as a supported Platform for Minecraft > 1.20.1 +- JiJ SQLite and Commonmark dependencies, allowing better compatibility and removing the SQLite JDBC dependency + # 1.3.0 - Message Embeds to better represent Minecraft messages on Discord - Fix `/link` Minecraft command not being registered on Forge diff --git a/README.md b/README.md index 94b7c7d..17cf69f 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,7 @@ to see how much is already implemented. This mod has a few dependencies, some of which are not specified directly as they're technically optional: - The Kotlin Implementation for the platform you're running. (e.g. [Kotlin For Forge](https://modrinth.com/mod/kotlin-for-forge) or [Fabric Language Kotlin](https://modrinth.com/mod/fabric-language-kotlin)) -- The Forge Config API (Included in Forge, [extra mod for Fabric](https://modrinth.com/mod/forge-config-api-port)) -- The SQLite Database Driver. (This is included in [Ledger](https://modrinth.com/mod/ledger) but also [available separately](https://modrinth.com/plugin/sqlite-jdbc)) +- The (Neo-)Forge Config API (Included in NeoForge, [extra mod for Fabric](https://modrinth.com/mod/forge-config-api-port)) ## Implementation - [JDA](https://jda.wiki) library to communicate with the Discord API. diff --git a/build.gradle.kts b/build.gradle.kts index 02b453d..474bfee 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,32 +1,29 @@ -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import dev.architectury.plugin.ArchitectPluginExtension -import net.fabricmc.loom.api.LoomGradleExtensionAPI -import net.fabricmc.loom.task.RemapJarTask +import org.jetbrains.kotlin.gradle.utils.extendsFrom import java.nio.charset.StandardCharsets +import java.text.SimpleDateFormat +import java.util.* plugins { - // This is an Architectury repository, as such the relevant plugins are needed - id("architectury-plugin") version "3.4-SNAPSHOT" - id("dev.architectury.loom") version "1.6-SNAPSHOT" apply false - // The shadow plugin is used in both Architectury and when including JDA and Exposed - id("com.github.johnrengelman.shadow") version "8.1.1" apply false + // The shadow plugin is used by the fabric subproject to include dependencies + // I'm temporarily using a fork of the original plugin to resolve "Unsupported java classfile major version 65" + // see: https://github.com/johnrengelman/shadow/issues/911 + id("io.github.goooler.shadow") version "8.1.7" apply false // Since this mod/bot is written in Kotlin and expected to run on Minecraft and as such // the JVM, the Kotlin plugin is needed kotlin("jvm") version "1.9.23" // For generating documentation based on comments in the code id("org.jetbrains.dokka") version "1.9.10" java + // Required for NeoGradle + id("org.jetbrains.gradle.plugin.idea-ext") version "1.1.7" } -architectury { - val minecraftVersion: String by project - minecraft = minecraftVersion +repositories { + mavenCentral() } subprojects { - // All subprojects need Architectury and Kotlin - apply(plugin = "dev.architectury.loom") - apply(plugin = "architectury-plugin") + apply(plugin = "java") apply(plugin = "kotlin") apply(plugin = "org.jetbrains.dokka") @@ -34,7 +31,9 @@ subprojects { // sub- and root projects val minecraftVersion: String by project val modLoader = project.name - val modId = rootProject.name + val modId: String by project + val modName = rootProject.name + val modAuthor: String by project val isCommon = modLoader == rootProject.projects.common.name base { @@ -42,13 +41,16 @@ subprojects { archivesName.set("$modId-$modLoader-$minecraftVersion") } - configure { - silentMojangMappingsLicense() + extensions.configure { + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) + withSourcesJar() } repositories { mavenCentral() - maven(url = "https://maven.architectury.dev/") + maven(url = "https://maven.neoforged.net/releases/") + maven("https://repo.spongepowered.org/repository/maven-public/") { name = "Sponge / Mixin" } + maven("https://maven.blamejared.com") { name = "BlameJared Maven (JEI / CraftTweaker / Bookshelf)" } // For the parchment mappings maven(url = "https://maven.parchmentmc.org") maven(url = "https://maven.resourcefulbees.com/repository/maven-public/") @@ -69,57 +71,54 @@ subprojects { val sqliteJDBCVersion: String by project val commonmarkVersion: String by project - // This array gets used at multiple places, so it's easier to - // just specify all dependencies at once and re-use them. This - // also makes changing them later on easier. - val botDependencies = arrayOf( - // Library used to communicate with Discord, see https://jda.wiki - "net.dv8tion:JDA:$jdaVersion", - - // Library to interact with the SQLite database, - // see: https://github.com/JetBrains/Exposed - "org.jetbrains.exposed:exposed-core:$exposedVersion", - "org.jetbrains.exposed:exposed-dao:$exposedVersion", - "org.jetbrains.exposed:exposed-jdbc:$exposedVersion", - "org.jetbrains.exposed:exposed-kotlin-datetime:$exposedVersion", - - // Database driver that allows Exposed to communicate with - // the SQLite database. This will not be in the JAR and needs to be provided - // otherwise (e.g. https://www.curseforge.com/minecraft/mc-mods/sqlite-jdbc) - "org.xerial:sqlite-jdbc:$sqliteJDBCVersion", - - // Markdown parser used for formatting Discord messages in Minecraft - "org.commonmark:commonmark:$commonmarkVersion", - ) + // Configuration for shaded dependencies, get relocated to dev.erdragh.astralbot.shadowed + val shadowBotDep by configurations.creating { + isTransitive = true + } + // Configuration for JiJ-ed dependencies + val includeBotDep by configurations.creating { + isTransitive = false + } + // Configuration for libraries that are needed at runtime + val runtimeLib by configurations.creating { + isTransitive = true + } + configurations.implementation.extendsFrom(configurations.named("shadowBotDep")) + configurations.implementation.extendsFrom(configurations.named("includeBotDep")) + configurations.implementation.extendsFrom(configurations.named("runtimeLib")) dependencies { - // Minecraft Mod dependencies - "minecraft"("::$minecraftVersion") + runtimeLib("org.xerial:sqlite-jdbc:$sqliteJDBCVersion") + includeBotDep("org.xerial:sqlite-jdbc:$sqliteJDBCVersion") - @Suppress("UnstableApiUsage") - "mappings"(project.the().layered { - val parchmentVersion: String by project + runtimeLib("org.commonmark:commonmark:$commonmarkVersion") + includeBotDep("org.commonmark:commonmark:$commonmarkVersion") - officialMojangMappings() - parchment( - create( - group = "org.parchmentmc.data", - name = "parchment-$minecraftVersion", - version = parchmentVersion - ) - ) - }) + arrayOf( + // Library used to communicate with Discord, see https://jda.wiki + "net.dv8tion:JDA:$jdaVersion", - // Discord Bot dependencies - botDependencies.forEach { - implementation(it) { + // Library to interact with the SQLite database, + // see: https://github.com/JetBrains/Exposed + "org.jetbrains.exposed:exposed-core:$exposedVersion", + "org.jetbrains.exposed:exposed-dao:$exposedVersion", + "org.jetbrains.exposed:exposed-jdbc:$exposedVersion", + ).forEach { + runtimeLib(it) { + exclude(module = "opus-java") + exclude(group = "org.slf4j") + exclude(group = "org.jetbrains.kotlin") + exclude(group = "kotlinx") + } + shadowBotDep(it) { // opus-java is for audio, which this bot doesn't need exclude(module = "opus-java") // Kotlin would be included as a transitive dependency // on JDA and Exposed, but is already provided by the // respective Kotlin implementation of the mod loaders exclude(group = "org.jetbrains.kotlin") + exclude(group = "kotlinx") // Minecraft already ships with a logging system exclude(group = "org.slf4j") } @@ -132,92 +131,84 @@ subprojects { } tasks.jar { - // Results in the not remapped jars having a -dev at the end - archiveClassifier.set("dev") - } + from(rootProject.file("LICENSE")) { + rename { "${it}_$modId" } + } - tasks.named("remapJar") { - // Results in the remapped jar not having any extra bit in - // its file name, identifying it as the main distribution - archiveClassifier.set(null as String?) + manifest { + attributes( + "Specification-Title" to modId, + "Specification-Vendor" to modAuthor, + "Specification-Version" to archiveVersion, + "Implementation-Title" to project.name, + "Implementation-Version" to archiveVersion, + "Implementation-Vendor" to modAuthor, + "Implementation-Timestamp" to SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(Date()), + "Timestamp" to System.currentTimeMillis(), + "Built-On-Java" to "${System.getProperty("java.vm.version")} (${System.getProperty("java.vm.vendor")})", + "Built-On-Minecraft" to minecraftVersion + ) + } } tasks.processResources { - duplicatesStrategy = DuplicatesStrategy.EXCLUDE - filesMatching(listOf("META-INF/mods.toml", "fabric.mod.json")) { - expand("version" to project.version) + val version: String by project + val group: String by project + val minecraftVersionRange: String by project + val fabricApiVersion: String by project + val fabricLoaderVersion: String by project + val fabricKotlinVersion: String by project + val neoVersion: String by project + val neoVersionRange: String by project + val kffLoaderRange: String by project + val license: String by project + val description: String by project + val credits: String by project + + val expandProps = mapOf( + "version" to version, + "group" to group, //Else we target the task's group. + "minecraft_version" to minecraftVersion, + "minecraft_version_range" to minecraftVersionRange, + "fabric_version" to fabricApiVersion, + "fabric_loader_version" to fabricLoaderVersion, + "fabric_kotlin_version" to fabricKotlinVersion, + "neoforge_version" to neoVersion, + "neoforge_loader_version_range" to neoVersionRange, + "kff_loader_range" to kffLoaderRange, + "mod_name" to modName, + "mod_author" to modAuthor, + "mod_id" to modId, + "license" to license, + "description" to description, + "credits" to credits + ) + + filesMatching(listOf("pack.mcmeta", "*.mixins.json", "META-INF/mods.toml", "fabric.mod.json")) { + expand(expandProps) } + inputs.properties(expandProps) } - if (!isCommon) { - // The subprojects for the actual mod loaders need the common - // project and the dependencies shadowed into the jar, so the - // plugin is used here. - apply(plugin = "com.github.johnrengelman.shadow") - - configure { - platformSetupLoomIde() - } - - // This shadowCommon configuration is used to both shadow the - // common project and shadow the dependencies into the final - // JARs - val shadowCommon by configurations.creating { - isCanBeConsumed = false - isCanBeResolved = true - } - + if (isCommon) { + sourceSets.main.get().resources.srcDir("src/main/generated/resources") + } else { dependencies { - botDependencies.forEach { - if (!it.contains("sqlite-jdbc")) shadowCommon(it) { - // opus-java is for audio, which this bot doesn't need - exclude(module = "opus-java") - // Kotlin would be included as a transitive dependency - // on JDA and Exposed, but is already provided by the - // respective Kotlin implementation of the mod loaders - exclude(group = "org.jetbrains.kotlin") - exclude(group = "org.jetbrains.kotlinx") - // Minecraft already ships with a logging system - exclude(group = "org.slf4j") - } - } + implementation(project(":common")) } + } - tasks { - "shadowJar"(ShadowJar::class) { - // The resulting JAR of this task will be named ...-dev-shadow, - // as it has the dependencies shadowed into it, but hasn't been - // remapped yet. - archiveClassifier.set("dev-shadow") - configurations = listOf(shadowCommon) - - // This transforms the service files to make relocated Exposed work (see: https://github.com/JetBrains/Exposed/issues/1353) - mergeServiceFiles() - - // Forge restricts loading certain classes for security reasons. - // Luckily, shadow can relocate them to a different package. - relocate("org.apache.commons.collections4", "dev.erdragh.shadowed.org.apache.commons.collections4") - - // Relocating Exposed somewhere different so other mods not doing that don't run into issues (e.g. Ledger) - relocate("org.jetbrains.exposed", "dev.erdragh.shadowed.org.jetbrains.exposed") - - // Relocating jackson to prevent incompatibilities with other mods also bundling it (e.g. GroovyModLoader on Forge) - relocate("com.fasterxml.jackson", "dev.erdragh.shadowed.com.fasterxml.jackson") - - exclude(".cache/**") //Remove datagen cache from jar. - exclude("**/astralbot/datagen/**") //Remove data gen code from jar. - exclude("**/org/slf4j/**") - } + // Disables Gradle's custom module metadata from being published to maven. The + // metadata includes mapped dependencies which are not reasonably consumable by + // other mod developers. + tasks.withType { + enabled = false + } - "remapJar"(RemapJarTask::class) { - // This results in the remapped JAR being based on the JAR - // with the dependencies and common project shadowed into it. - dependsOn("shadowJar") - inputFile.set(named("shadowJar").flatMap { it.archiveFile }) - } - } - } else { - sourceSets.main.get().resources.srcDir("src/main/generated/resources") + tasks.withType { + options.encoding = "UTF-8" + targetCompatibility = JavaVersion.VERSION_17.majorVersion + sourceCompatibility = JavaVersion.VERSION_17.majorVersion } } diff --git a/common/.gitignore b/common/.gitignore new file mode 100644 index 0000000..c585e19 --- /dev/null +++ b/common/.gitignore @@ -0,0 +1 @@ +out \ No newline at end of file diff --git a/common/build.gradle.kts b/common/build.gradle.kts index e1cdd35..8a1ee68 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -1,14 +1,36 @@ -architectury { - val enabledPlatforms: String by rootProject - common(enabledPlatforms.split(",")) +plugins { + idea + java + `maven-publish` + id ("org.spongepowered.gradle.vanilla") version "0.2.1-SNAPSHOT" +} + +val minecraftVersion: String by project +val modId: String by project + +minecraft { + version(minecraftVersion) + if (file("src/main/resources/${modId}.accesswidener").exists()) + accessWideners(file("src/main/resources/${modId}.accesswidener")) } dependencies { val fabricLoaderVersion: String by project val forgeConfigAPIVersion: String by project - // We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies - // Do NOT use other classes from fabric loader - modImplementation("net.fabricmc:fabric-loader:${fabricLoaderVersion}") api("fuzs.forgeconfigapiport:forgeconfigapiport-common-neoforgeapi:$forgeConfigAPIVersion") + compileOnly("org.spongepowered:mixin:0.8.5") +} + +publishing { + publications { + register("mavenJava", MavenPublication::class) { + artifactId = base.archivesName.get() + from(components["java"]) + } + } + + repositories { + maven("file://${System.getenv("local_maven")}") + } } \ No newline at end of file diff --git a/common/src/main/kotlin/module-info.java b/common/src/main/kotlin/module-info.java deleted file mode 100644 index 42b2eb5..0000000 --- a/common/src/main/kotlin/module-info.java +++ /dev/null @@ -1,30 +0,0 @@ -module Minecraft.astralbot.common.main { - // For the Usage command - requires transitive jdk.management; - - // For just using Kotlin - requires transitive kotlin.stdlib; - requires transitive kotlinx.coroutines.core; - - // For SQL Interaction - requires transitive java.sql; - requires exposed.core; - requires exposed.dao; - requires exposed.jdbc; - - // For Discord Interaction - requires net.dv8tion.jda; - // For message parsing - requires org.commonmark; - - // For Minecraft itself - requires authlib; - requires minecraft.merged; - requires transitive org.slf4j; - requires brigadier; - - // For accessing the config - requires forgeconfigapiport.common.neoforgeapi; - - requires java.desktop; -} \ No newline at end of file diff --git a/common/src/main/resources/astralbot-common.mixins.json b/common/src/main/resources/astralbot-common.mixins.json index 215a460..c26658d 100644 --- a/common/src/main/resources/astralbot-common.mixins.json +++ b/common/src/main/resources/astralbot-common.mixins.json @@ -3,6 +3,7 @@ "minVersion": "0.8", "package": "dev.erdragh.astralbot.mixins", "compatibilityLevel": "JAVA_17", + "refmap": "${mod_id}.refmap.json", "server": [ "PlayerListMixin", "DedicatedPlayerListMixin" diff --git a/fabric/build.gradle.kts b/fabric/build.gradle.kts index 4106f77..2af5516 100644 --- a/fabric/build.gradle.kts +++ b/fabric/build.gradle.kts @@ -1,30 +1,118 @@ -architectury { - fabric() -} +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -val common: Configuration by configurations.creating { - configurations.compileClasspath.get().extendsFrom(this) - configurations.runtimeClasspath.get().extendsFrom(this) - configurations["developmentFabric"].extendsFrom(this) +plugins { + java + idea + `maven-publish` + id("fabric-loom") version "1.6-SNAPSHOT" + id("io.github.goooler.shadow") } -dependencies { - common(project(":common", configuration = "namedElements")) { - isTransitive = false - } - shadowCommon(project(path = ":common", configuration = "transformProductionFabric")) { - isTransitive = false - } +val modId: String by project + +val includeBotDep: Configuration by configurations.getting +val shadowBotDep: Configuration by configurations.getting +dependencies { + mappings(loom.officialMojangMappings()) val minecraftVersion: String by project val fabricLoaderVersion: String by project val fabricApiVersion: String by project val fabricKotlinVersion: String by project val forgeConfigAPIVersion: String by project + minecraft("com.mojang:minecraft:${minecraftVersion}") + modImplementation(group = "net.fabricmc", name = "fabric-loader", version = fabricLoaderVersion) modApi(group = "net.fabricmc.fabric-api", name = "fabric-api", version = "$fabricApiVersion+$minecraftVersion") modImplementation("net.fabricmc:fabric-language-kotlin:${fabricKotlinVersion}") modApi("fuzs.forgeconfigapiport:forgeconfigapiport-fabric:$forgeConfigAPIVersion") + + includeBotDep.dependencies.forEach { include(it) } +} + +loom { + if (project(":common").file("src/main/resources/${modId}.accesswidener").exists()) + accessWidenerPath.set(project(":common").file("src/main/resources/${modId}.accesswidener")) + + @Suppress("UnstableApiUsage") + mixin { defaultRefmapName.set("${modId}.refmap.json") } + + runs { + named("client") { + client() + configName = "Fabric Client" + ideConfigGenerated(true) + runDir("run") + } + named("server") { + server() + configName = "Fabric Server" + ideConfigGenerated(true) + runDir("run") + } + } +} + +tasks { + withType { + source(project(":common").sourceSets.main.get().allSource) + } + withType { + source(project(":common").sourceSets.main.get().allSource) + } + + javadoc { source(project(":common").sourceSets.main.get().allJava) } + + jar { + archiveClassifier.set("dev") + } + + shadowJar { + archiveClassifier.set("dev-shadow") + + configurations = listOf(shadowBotDep) + + // This transforms the service files to make relocated Exposed work (see: https://github.com/JetBrains/Exposed/issues/1353) + mergeServiceFiles() + + // Relocating Exposed somewhere different so other mods not doing that don't run into issues (e.g. Ledger) + relocate("org.jetbrains.exposed", "dev.erdragh.shadowed.org.jetbrains.exposed") + + // Relocating jackson to prevent incompatibilities with other mods also bundling it (e.g. GroovyModLoader on Forge) + relocate("com.fasterxml.jackson", "dev.erdragh.shadowed.com.fasterxml.jackson") + + exclude(".cache/**") //Remove datagen cache from jar. + exclude("**/astralbot/datagen/**") //Remove data gen code from jar. + exclude("**/org/slf4j/**") + + exclude("kotlinx/**") + exclude("_COROUTINE/**") + exclude("**/org/jetbrains/annotations/*") + exclude("**/org/intellij/**") + } + + remapJar { + inputFile.set(named("shadowJar").get().archiveFile) + dependsOn("shadowJar") + } + + named("sourcesJar", Jar::class) { from(project(":common").sourceSets.main.get().allSource) } + + processResources { from(project(":common").sourceSets.main.get().resources) } +} + +publishing { + publications { + register("mavenJava", MavenPublication::class) { + artifactId = base.archivesName.get() + from(components["java"]) + } + } + + repositories { + maven("file://${System.getenv("local_maven")}") + } } \ No newline at end of file diff --git a/fabric/gradle.properties b/fabric/gradle.properties index 9934aec..e69de29 100644 --- a/fabric/gradle.properties +++ b/fabric/gradle.properties @@ -1,2 +0,0 @@ -fabricApiVersion=0.97.0 -fabricKotlinVersion=1.10.19+kotlin.1.9.23 \ No newline at end of file diff --git a/fabric/src/main/resources/astralbot.mixins.json b/fabric/src/main/resources/astralbot.mixins.json index 5dfcea1..2e68eba 100644 --- a/fabric/src/main/resources/astralbot.mixins.json +++ b/fabric/src/main/resources/astralbot.mixins.json @@ -3,6 +3,7 @@ "minVersion": "0.8", "package": "dev.erdragh.astralbot.mixins.fabric", "compatibilityLevel": "JAVA_17", + "refmap": "${mod_id}.refmap.json", "mixins": [ ], "client": [ diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index f3ff4ab..4d4bb75 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -1,18 +1,18 @@ { "schemaVersion": 1, - "id": "astralbot", + "id": "${mod_id}", "version": "${version}", - "name": "AstralBot", - "description": "Discord Bot and Minecraft mod in one bundle.", + "name": "${mod_name}", + "description": "${description}", "authors": [ - "Erdragh" + "${mod_author}" ], "contact": { "website": "https://modrinth.com/mod/astralbot", "repo": "https://github.com/Erdragh/AstralBot", "issues": "https://github.com/Erdragh/AstralBot/issues" }, - "license": "MIT Licence", + "license": "${license}", "icon": "icon.png", "environment": "*", "entrypoints": { @@ -29,9 +29,9 @@ ], "depends": { "fabric": "*", - "minecraft": ">=1.20.1", + "minecraft": ">=${minecraft_version}", "java": ">=17", - "fabric-language-kotlin": ">=1.9.0", - "forgeconfigapiport": ">=8.0.0" + "fabric-language-kotlin": ">=${fabric_kotlin_version}", + "forgeconfigapiport": ">=20.0.0" } } \ No newline at end of file diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts deleted file mode 100644 index 8d6603a..0000000 --- a/forge/build.gradle.kts +++ /dev/null @@ -1,60 +0,0 @@ -architectury { - forge() -} - -loom { - forge { - mixinConfig("astralbot-common.mixins.json") - mixinConfig("astralbot.mixins.json") - } - // This sets up data generation. At the time of writing this - // Comment, this is useless, as there are no resources to be - // generated. I want to keep it in as a reference tho. - runs { - create("data") { - data() - programArgs("--all", "--mod", "astralbot") - programArgs("--output", project(":common").file("src/main/generated/resources").absolutePath) - programArgs("--existing", project(":common").file("src/main/resources").absolutePath) - } - } -} - -val common: Configuration by configurations.creating { - configurations.compileClasspath.get().extendsFrom(this) - configurations.runtimeClasspath.get().extendsFrom(this) - configurations["developmentForge"].extendsFrom(this) -} - -dependencies { - common(project(":common", configuration = "namedElements")) { - isTransitive = false - } - shadowCommon(project(path = ":common", configuration = "transformProductionForge")) { - isTransitive = false - } - - val minecraftVersion: String by project - val forgeVersion: String by project - val kotlinForgeVersion: String by project - val forgeConfigAPIVersion: String by project - - forge(group = "net.minecraftforge", name = "forge", version = "$minecraftVersion-$forgeVersion") - // Adds KFF as dependency and Kotlin libs - implementation("thedarkcolour:kotlinforforge:$kotlinForgeVersion") - - val jdaVersion: String by project - - // This *should* theoretically fix the Forge development environment not having - // access to certain classes, but I haven't gotten it to work just yet. - forgeRuntimeLibrary("net.dv8tion:JDA:$jdaVersion") { - exclude(module = "opus-java") - exclude(group = "org.jetbrains.kotlin") - exclude(group = "org.slf4j") - } - - // On 1.20.2 upwards, the forge config api port either reimplements neo's - // or lexforge's config API. I chose to use Neo's by default, resulting in - // an additional dependency on the lexforge side. - modApi("fuzs.forgeconfigapiport:forgeconfigapiport-forge:$forgeConfigAPIVersion") -} \ No newline at end of file diff --git a/forge/gradle.properties b/forge/gradle.properties deleted file mode 100644 index b7f4c6d..0000000 --- a/forge/gradle.properties +++ /dev/null @@ -1,3 +0,0 @@ -loom.platform=forge -forgeVersion=49.0.49 -kotlinForgeVersion=4.10.0 \ No newline at end of file diff --git a/forge/src/main/kotlin/dev/erdragh/astralbot/forge/event/SystemMessageEvent.kt b/forge/src/main/kotlin/dev/erdragh/astralbot/forge/event/SystemMessageEvent.kt deleted file mode 100644 index d1b2362..0000000 --- a/forge/src/main/kotlin/dev/erdragh/astralbot/forge/event/SystemMessageEvent.kt +++ /dev/null @@ -1,8 +0,0 @@ -package dev.erdragh.astralbot.forge.event - -import net.minecraft.network.chat.Component -import net.minecraftforge.eventbus.api.Cancelable -import net.minecraftforge.eventbus.api.Event - -@Cancelable -class SystemMessageEvent(var message: Component) : Event() \ No newline at end of file diff --git a/forge/src/main/resources/META-INF/mods.toml b/forge/src/main/resources/META-INF/mods.toml deleted file mode 100644 index e75bed8..0000000 --- a/forge/src/main/resources/META-INF/mods.toml +++ /dev/null @@ -1,34 +0,0 @@ -modLoader = "kotlinforforge" -loaderVersion = "[4.6,)" -license = "MIT License" -issueTrackerURL = "https://github.com/Erdragh/AstralBot/issues" - -[[mods]] -modId = "astralbot" -version = "${version}" -displayName = "AstralBot" -displayURL = "https://modrinth.com/mod/astralbot" -logoFile = "icon.png" -authors = "Erdragh" -description = "Discord Bot and Minecraft Mod in one bundle." - -[[dependencies.astralbot]] -modId = "forge" -mandatory = true -versionRange = "[47,)" -ordering = "NONE" -side = "BOTH" - -[[dependencies.astralbot]] -modId = "minecraft" -mandatory = true -versionRange = "[1.20,)" -ordering = "NONE" -side = "BOTH" - -[[dependencies.astralbot]] -modId = "forgeconfigapiport" -mandatory = true -versionRange = "[20,)" -ordering = "NONE" -side = "BOTH" \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 7d4726d..59be9e6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,24 +2,40 @@ kotlin.code.style=official org.gradle.jvmargs=-Xmx3G # Minecraft things -enabledPlatforms=fabric,forge -# Specified here because it's used in both the fabric and common subproject +enabledPlatforms=fabric,neoforge + +# Fabric fabricLoaderVersion=0.15.10 +fabricApiVersion=0.97.0 +fabricKotlinVersion=1.10.19+kotlin.1.9.23 + +# Neo +neoVersion=20.4.233 +neoVersionRange=[20.4,20.5) +kotlinForgeVersion=4.10.0 +kffLoaderRange=[4,) -version=1.3.0 +version=1.4.0 group=dev.erdragh.astralbot +modId=astralbot +modAuthor=Erdragh + +license=MIT +description=Discord Bot and Minecraft Mod in one bundle. +credits=Erdragh minecraftVersion=1.20.4 +minecraftVersionRange=[1.20.4,) parchmentVersion=2024.04.14 forgeConfigAPIVersion=20.4.3 # Discord Interactions -jdaVersion=5.0.0-beta.23 +jdaVersion=5.0.0-beta.24 # Database Interactions -exposedVersion=0.49.0 -sqliteJDBCVersion=3.44.1.0 +exposedVersion=0.50.1 +sqliteJDBCVersion=3.45.3.0 # Message parsing commonmarkVersion=0.22.0 \ No newline at end of file diff --git a/neoforge/.gitignore b/neoforge/.gitignore new file mode 100644 index 0000000..d8aff51 --- /dev/null +++ b/neoforge/.gitignore @@ -0,0 +1,2 @@ +runs +out \ No newline at end of file diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts new file mode 100644 index 0000000..1f77fe6 --- /dev/null +++ b/neoforge/build.gradle.kts @@ -0,0 +1,137 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + idea + `maven-publish` + java + id("net.neoforged.gradle.userdev") version "7.0.136" + id("io.github.goooler.shadow") +} + +val modId: String by project + +jarJar.enable() + +val includeBotDep: Configuration by configurations.getting +val shadowBotDep: Configuration by configurations.getting +val runtimeLib: Configuration by configurations.getting + +// Automatically enable neoforge AccessTransformers if the file exists +// This location is hardcoded in FML and can not be changed. +// https://github.com/neoforged/FancyModLoader/blob/a952595eaaddd571fbc53f43847680b00894e0c1/loader/src/main/java/net/neoforged/fml/loading/moddiscovery/ModFile.java#L118 +val transformerFile = file("src/main/resources/META-INF/accesstransformer.cfg") +if (transformerFile.exists()) + minecraft.accessTransformers.file(transformerFile) + +runs { + configureEach { modSource(project.sourceSets.main.get()) } + + create("client") { + systemProperty("neoforge.enabledGameTestNamespaces", modId) + + dependencies { + runtime(runtimeLib) + } + } + + create("server") { + systemProperty("neoforge.enabledGameTestNamespaces", modId) + programArgument("--nogui") + dependencies { + runtime(runtimeLib) + } + } + + create("gameTestServer") { + systemProperty("neoforge.enabledGameTestNamespaces", modId) + dependencies { + runtime(runtimeLib) + } + } + + create("data") { + programArguments.addAll( + "--mod", modId, + "--all", + "--output", file("src/generated/resources").absolutePath, + "--existing", file("src/main/resources/").absolutePath + ) + dependencies { + runtime(runtimeLib) + } + } +} + +sourceSets.main.get().resources.srcDir("src/generated/resources") + +dependencies { + val minecraftVersion: String by project + val neoVersion: String by project + val kotlinForgeVersion: String by project + + implementation(group = "net.neoforged", name = "neoforge", version = neoVersion) + // Adds KFF as dependency and Kotlin libs + implementation("thedarkcolour:kotlinforforge-neoforge:$kotlinForgeVersion") + + includeBotDep.dependencies.forEach { jarJar(it) } +} + +// NeoGradle compiles the game, but we don't want to add our common code to the game's code +val notNeoTask: Spec = Spec { !it.name.startsWith("neo") } + +tasks { + withType().matching(notNeoTask).configureEach { source(project(":common").sourceSets.main.get().allSource) } + withType().matching(notNeoTask).configureEach { + source(project(":common").sourceSets.main.get().allSource) + } + + withType().matching(notNeoTask).configureEach { source(project(":common").sourceSets.main.get().allJava) } + + shadowJar { + archiveClassifier = null + configurations = listOf(shadowBotDep) + + // This transforms the service files to make relocated Exposed work (see: https://github.com/JetBrains/Exposed/issues/1353) + mergeServiceFiles() + + // Forge restricts loading certain classes for security reasons. + // Luckily, shadow can relocate them to a different package. + relocate("org.apache.commons.collections4", "dev.erdragh.shadowed.org.apache.commons.collections4") + + // Relocating Exposed somewhere different so other mods not doing that don't run into issues (e.g. Ledger) + relocate("org.jetbrains.exposed", "dev.erdragh.shadowed.org.jetbrains.exposed") + + // Relocating jackson to prevent incompatibilities with other mods also bundling it (e.g. GroovyModLoader on Forge) + relocate("com.fasterxml.jackson", "dev.erdragh.shadowed.com.fasterxml.jackson") + + exclude(".cache/**") //Remove datagen cache from jar. + exclude("**/astralbot/datagen/**") //Remove data gen code from jar. + exclude("**/org/slf4j/**") + + exclude("kotlinx/**") + exclude("_COROUTINE/**") + exclude("**/org/jetbrains/annotations/*") + exclude("**/org/intellij/**") + } + + jarJar.configure { + dependsOn(shadowJar) + } + + named("sourcesJar", Jar::class) { from(project(":common").sourceSets.main.get().allSource) } + + processResources { from(project(":common").sourceSets.main.get().resources) } +} + +publishing { + publications { + register("mavenJava", MavenPublication::class) { + artifactId = base.archivesName.get() + artifact(tasks.jar) + } + } + + repositories { + maven("file://${System.getenv("local_maven")}") + } +} \ No newline at end of file diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties new file mode 100644 index 0000000..e69de29 diff --git a/forge/src/main/java/dev/erdragh/astralbot/mixins/forge/PlayerListMixin.java b/neoforge/src/main/java/dev/erdragh/astralbot/mixins/forge/PlayerListMixin.java similarity index 81% rename from forge/src/main/java/dev/erdragh/astralbot/mixins/forge/PlayerListMixin.java rename to neoforge/src/main/java/dev/erdragh/astralbot/mixins/forge/PlayerListMixin.java index 3efddb6..4193cd1 100644 --- a/forge/src/main/java/dev/erdragh/astralbot/mixins/forge/PlayerListMixin.java +++ b/neoforge/src/main/java/dev/erdragh/astralbot/mixins/forge/PlayerListMixin.java @@ -1,10 +1,10 @@ package dev.erdragh.astralbot.mixins.forge; -import dev.erdragh.astralbot.forge.event.SystemMessageEvent; +import dev.erdragh.astralbot.neoforge.event.SystemMessageEvent; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.players.PlayerList; -import net.minecraftforge.common.MinecraftForge; +import net.neoforged.neoforge.common.NeoForge; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -16,6 +16,6 @@ public abstract class PlayerListMixin { @Inject(method = "broadcastSystemMessage(Lnet/minecraft/network/chat/Component;Ljava/util/function/Function;Z)V", at = @At("HEAD"), cancellable = true) private void onSendGameMessage(Component message, Function playerMessageFactory, boolean overlay, CallbackInfo ci) { - MinecraftForge.EVENT_BUS.post(new SystemMessageEvent(message)); + NeoForge.EVENT_BUS.post(new SystemMessageEvent(message)); } } \ No newline at end of file diff --git a/forge/src/main/kotlin/dev/erdragh/astralbot/forge/BotMod.kt b/neoforge/src/main/kotlin/dev/erdragh/astralbot/neoforge/BotMod.kt similarity index 66% rename from forge/src/main/kotlin/dev/erdragh/astralbot/forge/BotMod.kt rename to neoforge/src/main/kotlin/dev/erdragh/astralbot/neoforge/BotMod.kt index 68dc355..14625d4 100644 --- a/forge/src/main/kotlin/dev/erdragh/astralbot/forge/BotMod.kt +++ b/neoforge/src/main/kotlin/dev/erdragh/astralbot/neoforge/BotMod.kt @@ -1,28 +1,27 @@ -package dev.erdragh.astralbot.forge +package dev.erdragh.astralbot.neoforge import dev.erdragh.astralbot.* import dev.erdragh.astralbot.commands.minecraft.registerMinecraftCommands import dev.erdragh.astralbot.config.AstralBotConfig import dev.erdragh.astralbot.config.AstralBotTextConfig -import dev.erdragh.astralbot.forge.event.SystemMessageEvent +import dev.erdragh.astralbot.neoforge.event.SystemMessageEvent import dev.erdragh.astralbot.handlers.DiscordMessageComponent -import fuzs.forgeconfigapiport.forge.api.neoforge.v4.NeoForgeConfigRegistry import net.minecraft.server.level.ServerPlayer -import net.minecraftforge.event.RegisterCommandsEvent -import net.minecraftforge.event.ServerChatEvent -import net.minecraftforge.event.entity.player.PlayerEvent -import net.minecraftforge.event.server.ServerStartedEvent -import net.minecraftforge.event.server.ServerStoppingEvent -import net.minecraftforge.fml.ModLoadingContext -import net.minecraftforge.fml.common.Mod -import net.minecraftforge.fml.config.ModConfig -import thedarkcolour.kotlinforforge.forge.FORGE_BUS +import net.neoforged.fml.ModLoadingContext +import net.neoforged.fml.common.Mod +import net.neoforged.fml.config.ModConfig +import net.neoforged.neoforge.event.RegisterCommandsEvent +import net.neoforged.neoforge.event.ServerChatEvent +import net.neoforged.neoforge.event.entity.player.PlayerEvent +import net.neoforged.neoforge.event.server.ServerStartedEvent +import net.neoforged.neoforge.event.server.ServerStoppingEvent +import thedarkcolour.kotlinforforge.neoforge.forge.FORGE_BUS @Mod("astralbot") object BotMod { init { - NeoForgeConfigRegistry.INSTANCE.register(MODID, ModConfig.Type.SERVER, AstralBotConfig.SPEC) - NeoForgeConfigRegistry.INSTANCE.register(MODID, ModConfig.Type.SERVER, AstralBotTextConfig.SPEC, "astralbot-text.toml") + ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, AstralBotConfig.SPEC) + ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, AstralBotTextConfig.SPEC, "astralbot-text.toml") FORGE_BUS.addListener(::onServerStart) FORGE_BUS.addListener(::onServerStop) FORGE_BUS.addListener(::onChatMessage) diff --git a/neoforge/src/main/kotlin/dev/erdragh/astralbot/neoforge/event/SystemMessageEvent.kt b/neoforge/src/main/kotlin/dev/erdragh/astralbot/neoforge/event/SystemMessageEvent.kt new file mode 100644 index 0000000..c1b358a --- /dev/null +++ b/neoforge/src/main/kotlin/dev/erdragh/astralbot/neoforge/event/SystemMessageEvent.kt @@ -0,0 +1,7 @@ +package dev.erdragh.astralbot.neoforge.event + +import net.minecraft.network.chat.Component +import net.neoforged.bus.api.Event +import net.neoforged.bus.api.ICancellableEvent + +class SystemMessageEvent(var message: Component) : Event(), ICancellableEvent \ No newline at end of file diff --git a/neoforge/src/main/resources/META-INF/mods.toml b/neoforge/src/main/resources/META-INF/mods.toml new file mode 100644 index 0000000..4d4e7e8 --- /dev/null +++ b/neoforge/src/main/resources/META-INF/mods.toml @@ -0,0 +1,32 @@ +modLoader = "kotlinforforge" +loaderVersion = "${kff_loader_range}" +license = "${license}" +issueTrackerURL = "https://github.com/Erdragh/AstralBot/issues" + +[[mixins]] +config = "astralbot-common.mixins.json" +[[mixins]] +config = "astralbot.mixins.json" + +[[mods]] +modId = "${mod_id}" +version = "${version}" +displayName = "${mod_name}" +displayURL = "https://modrinth.com/mod/astralbot" +logoFile = "icon.png" +authors = "${mod_author}" +description = "${description}" + +[[dependencies.${mod_id}]] +modId = "neoforge" +type = "required" +versionRange = "${neoforge_loader_version_range}" +ordering = "NONE" +side = "BOTH" + +[[dependencies.${mod_id}]] +modId = "minecraft" +type = "required" +versionRange = "${minecraft_version_range}" +ordering = "NONE" +side = "BOTH" \ No newline at end of file diff --git a/forge/src/main/resources/astralbot.mixins.json b/neoforge/src/main/resources/astralbot.mixins.json similarity index 85% rename from forge/src/main/resources/astralbot.mixins.json rename to neoforge/src/main/resources/astralbot.mixins.json index 4b9f0a4..81bac46 100644 --- a/forge/src/main/resources/astralbot.mixins.json +++ b/neoforge/src/main/resources/astralbot.mixins.json @@ -3,6 +3,7 @@ "minVersion": "0.8", "package": "dev.erdragh.astralbot.mixins.forge", "compatibilityLevel": "JAVA_17", + "refmap": "${mod_id}.refmap.json", "server": [ "PlayerListMixin" ], diff --git a/forge/src/main/resources/pack.mcmeta b/neoforge/src/main/resources/pack.mcmeta similarity index 100% rename from forge/src/main/resources/pack.mcmeta rename to neoforge/src/main/resources/pack.mcmeta diff --git a/settings.gradle.kts b/settings.gradle.kts index 55b0a42..11ac206 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,13 +1,13 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") -rootProject.name = "astralbot" +rootProject.name = "AstralBot" pluginManagement { repositories { mavenCentral() - maven(url = "https://maven.architectury.dev/") - maven(url = "https://maven.neoforged.net/releases/") - maven(url = "https://maven.resourcefulbees.com/repository/maven-public/") + maven("https://maven.fabricmc.net/") { name = "Fabric" } + maven("https://maven.neoforged.net/releases/") { name = "NeoForge" } + maven("https://repo.spongepowered.org/repository/maven-public/") { name = "Sponge Snapshots" } gradlePluginPortal() } } @@ -16,6 +16,4 @@ plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" } -include("common") -include("fabric") -include("forge") \ No newline at end of file +include("common", "fabric", "neoforge") \ No newline at end of file