diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ee65bc7..7b15886 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,7 +19,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: validate gradle wrapper uses: gradle/actions/wrapper-validation@v5 - name: setup jdk ${{ matrix.java }} diff --git a/build.gradle.kts b/build.gradle.kts index 4093dbf..48939ac 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,50 +1,21 @@ -@file:Suppress("UnstableApiUsage", "PropertyName") - -import org.apache.tools.ant.taskdefs.condition.Os - +import com.smushytaco.lwjgl_gradle.Preset plugins { - id("fabric-loom") + alias(libs.plugins.loom) + alias(libs.plugins.lwjgl) java } - -val lwjglVersion = providers.gradleProperty("lwjgl_version") -val lwjglNatives = when { - Os.isFamily(Os.FAMILY_UNIX) && !Os.isFamily(Os.FAMILY_MAC) -> "natives-linux" - Os.isFamily(Os.FAMILY_WINDOWS) -> "natives-windows" - Os.isFamily(Os.FAMILY_MAC) -> "natives-macos${if (Os.isArch("aarch64")) "-arm64" else ""}" - else -> error("Unsupported OS") -} - val modVersion = providers.gradleProperty("mod_version") val modGroup = providers.gradleProperty("mod_group") val modName = providers.gradleProperty("mod_name") -val btaChannel = providers.gradleProperty("bta_channel") -val btaVersion = providers.gradleProperty("bta_version") - -val loaderVersion = providers.gradleProperty("loader_version") -val legacyLwjglVersion = providers.gradleProperty("legacy_lwjgl_version") - -val halplibeVersion = providers.gradleProperty("halplibe_version") -val modMenuVersion = providers.gradleProperty("mod_menu_version") - -val slf4jApiVersion = providers.gradleProperty("slf4j_api_version") -val log4jVersion = providers.gradleProperty("log4j_version") -val guavaVersion = providers.gradleProperty("guava_version") -val gsonVersion = providers.gradleProperty("gson_version") -val commonsLang3Version = providers.gradleProperty("commons_lang3_version") - -val javaVersion = providers.gradleProperty("java_version") +val javaVersion = libs.versions.java.map { it.toInt() } +base.archivesName = modName group = modGroup.get() -base.archivesName = modName.get() version = modVersion.get() - loom { - noIntermediateMappings() - customMinecraftMetadata.set("https://downloads.betterthanadventure.net/bta-client/${btaChannel.get()}/v${btaVersion.get()}/manifest.json") + customMinecraftMetadata.set("https://downloads.betterthanadventure.net/bta-client/${libs.versions.btaChannel.get()}/v${libs.versions.bta.get()}/manifest.json") } - repositories { mavenCentral() maven("https://jitpack.io") @@ -55,11 +26,11 @@ repositories { patternLayout { artifact("[organisation]/releases/download/v[revision]/[module].jar") } metadataSources { artifact() } } - ivy("https://downloads.betterthanadventure.net/bta-client/${btaChannel.get()}/") { + ivy("https://downloads.betterthanadventure.net/bta-client/${libs.versions.btaChannel.get()}/") { patternLayout { artifact("/v[revision]/client.jar") } metadataSources { artifact() } } - ivy("https://downloads.betterthanadventure.net/bta-server/${btaChannel.get()}/") { + ivy("https://downloads.betterthanadventure.net/bta-server/${libs.versions.btaChannel.get()}/") { patternLayout { artifact("/v[revision]/server.jar") } metadataSources { artifact() } } @@ -68,75 +39,73 @@ repositories { metadataSources { artifact() } } } - +lwjgl { + version = libs.versions.lwjgl + implementation(Preset.MINIMAL_OPENGL) +} dependencies { - minecraft("::${btaVersion.get()}") - mappings(loom.layered {}) - - // https://piston-data.mojang.com/v1/objects/43db9b498cb67058d2e12d394e6507722e71bb45/client.jar - modRuntimeOnly("objects:client:43db9b498cb67058d2e12d394e6507722e71bb45") - // If you do not need Halplibe you can comment out or delete this line. - modImplementation("turniplabs:halplibe:${halplibeVersion.get()}") - modImplementation("turniplabs:modmenu-bta:${modMenuVersion.get()}") - modImplementation("net.fabricmc:fabric-loader:${loaderVersion.get()}") - modImplementation("com.github.Better-than-Adventure:legacy-lwjgl3:${legacyLwjglVersion.get()}") - - implementation(platform("org.lwjgl:lwjgl-bom:${lwjglVersion.get()}")) - implementation("org.slf4j:slf4j-api:${slf4jApiVersion.get()}") - - implementation("com.google.guava:guava:${guavaVersion.get()}") - implementation("com.google.code.gson:gson:${gsonVersion.get()}") - - implementation("org.apache.logging.log4j:log4j-slf4j2-impl:${log4jVersion.get()}") - implementation("org.apache.logging.log4j:log4j-core:${log4jVersion.get()}") - implementation("org.apache.logging.log4j:log4j-api:${log4jVersion.get()}") - implementation("org.apache.logging.log4j:log4j-1.2-api:${log4jVersion.get()}") - - implementation("org.apache.commons:commons-lang3:${commonsLang3Version.get()}") - include("org.apache.commons:commons-lang3:${commonsLang3Version.get()}") - - implementation("org.lwjgl:lwjgl:${lwjglVersion.get()}") - implementation("org.lwjgl:lwjgl-assimp:${lwjglVersion.get()}") - implementation("org.lwjgl:lwjgl-glfw:${lwjglVersion.get()}") - implementation("org.lwjgl:lwjgl-openal:${lwjglVersion.get()}") - implementation("org.lwjgl:lwjgl-opengl:${lwjglVersion.get()}") - implementation("org.lwjgl:lwjgl-stb:${lwjglVersion.get()}") - - runtimeOnly("org.lwjgl:lwjgl::$lwjglNatives") - runtimeOnly("org.lwjgl:lwjgl-assimp::$lwjglNatives") - runtimeOnly("org.lwjgl:lwjgl-glfw::$lwjglNatives") - runtimeOnly("org.lwjgl:lwjgl-openal::$lwjglNatives") - runtimeOnly("org.lwjgl:lwjgl-opengl::$lwjglNatives") - runtimeOnly("org.lwjgl:lwjgl-stb::$lwjglNatives") + minecraft("::${libs.versions.bta.get()}") + + runtimeOnly(libs.clientJar) + implementation(libs.loader) + // If you do not need Halplibe you can comment out or delete this line. + implementation(libs.halplibe) + implementation(libs.modMenu) + implementation(libs.legacyLwjgl) + + implementation(libs.slf4jApi) + implementation(libs.guava) + implementation(libs.log4j.slf4j2.impl) + implementation(libs.log4j.core) + implementation(libs.log4j.api) + implementation(libs.log4j.api12) + implementation(libs.gson) + + implementation(libs.commonsLang3) + include(libs.commonsLang3) +} +java { + toolchain { + languageVersion = javaVersion.map { JavaLanguageVersion.of(it) } + vendor = JvmVendorSpec.ADOPTIUM + } + sourceCompatibility = JavaVersion.toVersion(javaVersion.get()) + targetCompatibility = JavaVersion.toVersion(javaVersion.get()) + withSourcesJar() +} +val licenseFile = run { + val rootLicense = layout.projectDirectory.file("LICENSE") + val parentLicense = layout.projectDirectory.file("../LICENSE") + when { + rootLicense.asFile.exists() -> { + logger.lifecycle("Using LICENSE from project root: {}", rootLicense.asFile) + rootLicense + } + parentLicense.asFile.exists() -> { + logger.lifecycle("Using LICENSE from parent directory: {}", parentLicense.asFile) + parentLicense + } + else -> { + logger.warn("No LICENSE file found in project or parent directory.") + null + } + } } - tasks { withType().configureEach { options.encoding = "UTF-8" - sourceCompatibility = javaVersion.get() - targetCompatibility = javaVersion.get() - if (javaVersion.get().toInt() > 8) options.release = javaVersion.get().toInt() + sourceCompatibility = javaVersion.get().toString() + targetCompatibility = javaVersion.get().toString() + if (javaVersion.get() > 8) options.release = javaVersion + } + named("updateDaemonJvm") { + languageVersion = libs.versions.gradleJava.map { JavaLanguageVersion.of(it.toInt()) } + vendor = JvmVendorSpec.ADOPTIUM } withType().configureEach { defaultCharacterEncoding = "UTF-8" } withType().configureEach { options.encoding = "UTF-8" } withType().configureEach { defaultCharacterEncoding = "UTF-8" } - named("jar") { - val rootLicense = layout.projectDirectory.file("LICENSE") - val parentLicense = layout.projectDirectory.file("../LICENSE") - val licenseFile = when { - rootLicense.asFile.exists() -> { - logger.lifecycle("Using LICENSE from project root: ${rootLicense.asFile}") - rootLicense - } - parentLicense.asFile.exists() -> { - logger.lifecycle("Using LICENSE from parent directory: ${parentLicense.asFile}") - parentLicense - } - else -> { - logger.warn("No LICENSE file found in project or parent directory.") - null - } - } + withType().configureEach { licenseFile?.let { from(it) { rename { original -> "${original}_${archiveBaseName.get()}" } @@ -144,37 +113,16 @@ tasks { } } processResources { - val stringModVersion = modVersion.get() - val stringLoaderVersion = loaderVersion.get() - val stringJavaVersion = javaVersion.get() - val stringHalplibeVersion = halplibeVersion.get() - val stringModMenuVersion = modMenuVersion.get() - inputs.property("modVersion", stringModVersion) - inputs.property("loaderVersion", stringLoaderVersion) - inputs.property("javaVersion", stringJavaVersion) - inputs.property("HalplibeVersion", stringHalplibeVersion) - inputs.property("modMenuVersion", stringModMenuVersion) - filesMatching("fabric.mod.json") { - expand( - mapOf( - "version" to stringModVersion, - "fabricloader" to stringLoaderVersion, - "halplibe" to stringHalplibeVersion, - "java" to stringJavaVersion, - "modmenu" to stringModMenuVersion - ) - ) - } - filesMatching("**/*.mixins.json") { expand(mapOf("java" to stringJavaVersion)) } - } - java { - toolchain { - languageVersion = JavaLanguageVersion.of(javaVersion.get()) - vendor = JvmVendorSpec.ADOPTIUM - } - sourceCompatibility = JavaVersion.toVersion(javaVersion.get().toInt()) - targetCompatibility = JavaVersion.toVersion(javaVersion.get().toInt()) - withSourcesJar() + val resourceMap = mapOf( + "version" to modVersion.get(), + "fabricloader" to libs.versions.loader.get(), + "halplibe" to libs.versions.halplibe.get(), + "java" to libs.versions.java.get(), + "modmenu" to libs.versions.modMenu.get() + ) + inputs.properties(resourceMap) + filesMatching("fabric.mod.json") { expand(resourceMap) } + filesMatching("**/*.mixins.json") { expand(resourceMap.filterKeys { it == "java" }) } } } // Removes LWJGL2 dependencies diff --git a/gradle.properties b/gradle.properties index 2c12702..33d97b7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,44 +7,11 @@ org.gradle.warning.mode = all # tasks instead, then this can (and should) be set to true. org.gradle.configuration-cache = false ########################################################################## -# Standard BTA Dependencies -# Check this on https://downloads.betterthanadventure.net/bta-client/ -bta_version = 7.3_04 -# Options are release, prerelease, nightly, and misc. -bta_channel = release -# Check this on https://maven.thesignalumproject.net/#/infrastructure/net/fabricmc/fabric-loader/ -loader_version = 0.17.3-bta.8 -# Check this on https://maven.thesignalumproject.net/#/infrastructure/fabric-loom/fabric-loom.gradle.plugin/ -loom_version = 1.13.0-bta -java_version = 8 -########################################################################## # Mod Properties mod_version = 1.0.0 mod_group = turniplabs mod_name = examplemod ########################################################################## -# Mod Dependencies -# Check this on https://github.com/Turnip-Labs/ModMenu/releases/latest/ -mod_menu_version = 3.0.0 -# Check this on https://github.com/Turnip-Labs/bta-halplibe/releases/latest/ -halplibe_version = 5.3.1 -# Check this on https://github.com/Better-than-Adventure/legacy-lwjgl3/releases/latest/ -legacy_lwjgl_version = 1.0.6 -########################################################################## -# 3rd Party Dependencies -# Check this on https://central.sonatype.com/artifact/org.slf4j/slf4j-api/ -slf4j_api_version = 2.0.17 -# Check this on https://central.sonatype.com/artifact/org.apache.logging.log4j/log4j-api/ -log4j_version = 2.20.0 -# Check this on https://central.sonatype.com/artifact/com.google.guava/guava/ -guava_version = 33.5.0-jre -# Check this on https://central.sonatype.com/artifact/com.google.code.gson/gson/ -gson_version = 2.13.2 -# Check this on https://central.sonatype.com/artifact/org.apache.commons/commons-lang3/ -commons_lang3_version = 3.19.0 -# This should match the version used by the current BTA release. -lwjgl_version = 3.3.3 -########################################################################## # Plugin Dependency # Check this on https://plugins.gradle.org/plugin/org.gradle.toolchains.foojay-resolver-convention/ foojay_resolver_version = 1.0.0 diff --git a/gradle/gradle-daemon-jvm.properties b/gradle/gradle-daemon-jvm.properties new file mode 100644 index 0000000..e409a46 --- /dev/null +++ b/gradle/gradle-daemon-jvm.properties @@ -0,0 +1,13 @@ +#This file is generated by updateDaemonJvm +toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/df211d3c3eefdc408b462041881bc575/redirect +toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/b41931cf1e70bc8e08d7dd19c343ef00/redirect +toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/df211d3c3eefdc408b462041881bc575/redirect +toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/b41931cf1e70bc8e08d7dd19c343ef00/redirect +toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/46949723aaa20c7b64d7ecfed7207034/redirect +toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/d6690dfd71c4c91e08577437b5b2beb0/redirect +toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/df211d3c3eefdc408b462041881bc575/redirect +toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/b41931cf1e70bc8e08d7dd19c343ef00/redirect +toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/3cd7045fca9a72cd9bc7d14a385e594c/redirect +toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/552c7bffe0370c66410a51c55985b511/redirect +toolchainVendor=ADOPTIUM +toolchainVersion=21 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..fe8b462 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,62 @@ +[versions] +########################################################################## +# Plugins +# Check this on https://github.com/FabricMC/fabric-loom/releases/latest/ +loom = "1.14-SNAPSHOT" +# Check this on https://plugins.gradle.org/plugin/com.smushytaco.lwjgl3/ +lwjglPlugin = "1.0.0" +########################################################################## +# Java Configuration +# The Java version the JDK will be for compiling and running code. +java = "8" +# The Java version the JDK will be for running Gradle. +gradleJava = "21" +########################################################################## +# Mod Dependencies +# Check this on https://downloads.betterthanadventure.net/bta-client/ +bta = "7.3_04" +# Options are release, prerelease, nightly, and misc. +btaChannel = "release" +# Check this on https://maven.thesignalumproject.net/#/infrastructure/net/fabricmc/fabric-loader/ +loader = "0.18.1-bta.9" +# Check this on https://github.com/Turnip-Labs/ModMenu/releases/latest/ +modMenu = "4.0.0" +# Check this on https://github.com/Turnip-Labs/bta-halplibe/releases/latest/ +halplibe = "5.3.2" +# Check this on https://github.com/Better-than-Adventure/legacy-lwjgl3/releases/latest/ +legacyLwjgl = "1.0.6" +########################################################################## +# Dependencies +# Check this on https://central.sonatype.com/artifact/org.slf4j/slf4j-api/ +slf4jApi = "2.0.17" +# Check this on https://central.sonatype.com/artifact/com.google.guava/guava/ +guava = "33.5.0-jre" +# Check this on https://central.sonatype.com/artifact/org.apache.logging.log4j/log4j-api/ +log4j = "2.20.0" +# Check this on https://central.sonatype.com/artifact/com.google.code.gson/gson/ +gson = "2.13.2" +# Check this on https://central.sonatype.com/artifact/org.apache.commons/commons-lang3/ +commonsLang3 = "3.20.0" +# This should match the version used by the current BTA release. +lwjgl = "3.3.3" +########################################################################## + +[libraries] +loader = { group = "net.fabricmc", name = "fabric-loader", version.ref = "loader" } +halplibe = { group = "turniplabs", name = "halplibe", version.ref = "halplibe" } +modMenu = { group = "turniplabs", name = "modmenu-bta", version.ref = "modMenu" } +legacyLwjgl = { group = "com.github.Better-than-Adventure", name = "legacy-lwjgl3", version.ref = "legacyLwjgl" } +slf4jApi = { group = "org.slf4j", name = "slf4j-api", version.ref = "slf4jApi" } +guava = { group = "com.google.guava", name = "guava", version.ref = "guava" } +log4j-slf4j2-impl = { group = "org.apache.logging.log4j", name = "log4j-slf4j2-impl", version.ref = "log4j" } +log4j-core = { group = "org.apache.logging.log4j", name = "log4j-core", version.ref = "log4j" } +log4j-api = { group = "org.apache.logging.log4j", name = "log4j-api", version.ref = "log4j" } +log4j-api12 = { group = "org.apache.logging.log4j", name = "log4j-1.2-api", version.ref = "log4j" } +gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" } +commonsLang3 = { group = "org.apache.commons", name = "commons-lang3", version.ref = "commonsLang3" } +# https://piston-data.mojang.com/v1/objects/43db9b498cb67058d2e12d394e6507722e71bb45/client.jar +clientJar = { group = "objects", name = "client", version = "43db9b498cb67058d2e12d394e6507722e71bb45" } + +[plugins] +loom = { id = "net.fabricmc.fabric-loom", version.ref = "loom" } +lwjgl = { id = "com.smushytaco.lwjgl3", version.ref = "lwjglPlugin" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f523375..8dcb8fb 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ # Check this on https://gradle.org/releases/ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle.kts b/settings.gradle.kts index 40b4221..1a7446a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,17 +1,58 @@ val modName = providers.gradleProperty("mod_name") rootProject.name = modName.get() pluginManagement { + fun isRepoHealthy(url: String): Boolean { + var connection: javax.net.ssl.HttpsURLConnection? = null + return try { + connection = java.net.URI(url).toURL().openConnection() as javax.net.ssl.HttpsURLConnection + connection.requestMethod = "HEAD" + connection.connectTimeout = 2000 + connection.readTimeout = 2000 + connection.instanceFollowRedirects = true + connection.connect() + val code = connection.responseCode + code in 200..399 + } catch (_: Exception) { + false + } finally { + connection?.disconnect() + } + } + fun repoUrlWithFallbacks(candidates: List): String { + if (candidates.isEmpty()) { + val badLink = "https://mock.httpstatus.io/500" + logger.error("No repositories have been provided. Defaulting to: {}", badLink) + return badLink + } + val chosenRepository = candidates.firstOrNull { isRepoHealthy(it) } ?: run { + if (candidates.size == 1) { + logger.error("\"{}\" could not be resolved.", candidates.first()) + } else { + logger.error("All {} repositories could not be resolved. Defaulting to: {}", candidates.size, candidates.first()) + } + return candidates.first() + } + logger.lifecycle("Using \"{}\" as the Fabric repository.", chosenRepository) + return chosenRepository + } repositories { - gradlePluginPortal() - maven("https://maven.fabricmc.net/") { name = "Fabric" } + maven( + repoUrlWithFallbacks( + listOf( + "https://maven.fabricmc.net", + "https://maven2.fabricmc.net", + "https://maven3.fabricmc.net" + ) + ) + ) { name = "Fabric" } maven("https://jitpack.io") { name = "Jitpack" } maven("https://maven.thesignalumproject.net/infrastructure") { name = "SignalumMavenInfrastructure" } + mavenCentral() + gradlePluginPortal() } val foojayResolverVersion = providers.gradleProperty("foojay_resolver_version") - val loomVersion = providers.gradleProperty("loom_version") plugins { id("org.gradle.toolchains.foojay-resolver-convention").version(foojayResolverVersion.get()) - id("fabric-loom").version(loomVersion.get()) } } plugins {