diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 000000000..69e15027d --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,8 @@ +plugins { + `kotlin-dsl` +} + +repositories { + mavenCentral() + maven("https://repo.polyfrost.org/releases") +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/org/polyfrost/gradle/addDependencies.kt b/buildSrc/src/main/kotlin/org/polyfrost/gradle/addDependencies.kt new file mode 100644 index 000000000..a18810a0f --- /dev/null +++ b/buildSrc/src/main/kotlin/org/polyfrost/gradle/addDependencies.kt @@ -0,0 +1,38 @@ +package org.polyfrost.gradle + +import org.gradle.api.Project +import org.gradle.api.artifacts.VersionCatalogsExtension +import org.gradle.kotlin.dsl.getByType + +fun Project.provideIncludedDependencies(version: Triple?, loader: String): List { // Either a String or ExternalModuleDependency + val libs = project + .extensions + .getByType() + .named("libs") + val deps = mutableListOf() + deps.addAll(libs.findBundle("kotlin").get().get()) + deps.addAll(libs.findBundle("kotlinx").get().get()) + deps.addAll(libs.findBundle("nightconfig").get().get()) + deps.add(libs.findLibrary("isolated-lwjgl3-loader").get().get()) + deps.add(libs.findLibrary("deftu-filestream").get().get()) + deps.add(libs.findLibrary("polyui").get().get()) + deps.add(libs.findLibrary("hypixel-modapi").get().get()) + deps.add(libs.findLibrary("hypixel-data").get().get()) + if (loader == "fabric") { + deps.add(libs.findLibrary("fabric-language-kotlin").get().get()) + } else if (version != null && version.second > 12) { // forge / neoforge + // TODO add KFF + } + val actualDeps = mutableListOf() + for (dep in deps) { + actualDeps.add(OCDependency(dep)) + } + if (version != null) { + actualDeps.add(OCDependency("org.polyfrost:universalcraft-${version.toMCVer()}-$loader:${libs.findVersion("universalcraft").get().displayName}", true)) + } + return actualDeps +} + +private fun Triple.toMCVer() = listOf(first, second, third).dropLastWhile { it == 0 }.joinToString(".") + +data class OCDependency(val dep: Any, val mod: Boolean = false) \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 38371acb5..1929b0ac7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ name=OneConfig mod_id=oneconfig version_major=1 version_minor=0 -version_patch=0-alpha.29 +version_patch=0-alpha.30 polyfrost.defaults.loom=3 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index aa3f7b624..1bcab87ef 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,20 +1,30 @@ [versions] # Libraries +# All kotlin = "2.0.20" kotlinx-coroutines = "1.8.1" kotlinx-atomicfu = "0.24.0" -kotlinx-abi = "0.14.0" +fabric-language-kotlin = "1.12.2+kotlin.2.0.20" polyui = "1.7.03" annotations = "24.1.0" -nightconfig = "3.6.6" hypixel-modapi = "1.0" +hypixel-data = "0.1.2" # Dep of hypixel-modapi + +# Not in risk of needing to be relaunched / bumped by JiJ +nightconfig = "3.6.6" +isolated-lwjgl3-loader = "0.1.1" +deftu-filestream = "0.4.1" # dep of isolated-lwjgl3-loader + +# Per version universalcraft = "299" +lwjgl = "3.3.3" # All downloaded by the isolated-lwjgl3-loader + +# Legacy only mixin = "0.8.4+build.2" -isolated-lwjgl3-loader = "0.1.1" -lwjgl = "3.3.3" # Natives downloaded by the isolated-lwjgl3-loader # Gradle +kotlinx-abi = "0.14.0" pgt = "0.6.6" shadow = "8.1.1" licenser = "2.0.1" @@ -33,8 +43,10 @@ junit-bom = { module = "org.junit:junit-bom", version.ref = "junit-bom" } mixin = { module = "org.polyfrost:polymixin", version.ref = "mixin" } isolated-lwjgl3-loader = { module = "org.polyfrost:isolated-lwjgl3-loader", version.ref = "isolated-lwjgl3-loader" } +deftu-filestream = { module = "dev.deftu:filestream", version.ref = "deftu-filestream" } hypixel-modapi = { module = "net.hypixel:mod-api", version.ref = "hypixel-modapi" } +hypixel-data = { module = "net.hypixel:hypixel-data", version.ref = "hypixel-data" } polyui = { module = "org.polyfrost:polyui", version.ref = "polyui" } @@ -58,6 +70,7 @@ kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" } kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm", version.ref = "kotlinx-coroutines" } kotlinx-atomicfu = { module = "org.jetbrains.kotlinx:atomicfu-jvm", version.ref = "kotlinx-atomicfu" } +fabric-language-kotlin = { module = "net.fabricmc:fabric-language-kotlin", version.ref = "fabric-language-kotlin" } [bundles] kotlin = ["kotlin-reflect", "kotlin-stdlib"] diff --git a/modules/dependencies/README.md b/modules/dependencies/README.md new file mode 100644 index 000000000..468cddc24 --- /dev/null +++ b/modules/dependencies/README.md @@ -0,0 +1,46 @@ +# OneConfig dependencies + +This directory contains the dependencies for the OneConfig project. + +## Complications +The dependencies we use are also used by various other projects. Hence, +we want to ensure that we always load the newest version of whatever +dependency we use. However, each mod loader we use has a different way +of handling dependencies, with varying levels of complexity: + +- **On Legacy Forge:** There is no built-in dependency system. If we have a + newer version of a dependency, we depend on a hack in the OneConfig + loader (which is required for Legacy Forge) known as "Relaunch." + Essential also uses the same system, but we have systems in place to + ensure both work together and always load the correct version of our + dependencies. +- **On modern Forge without JiJ:** In later versions, Forge has + added a similar system to Fabric's JiJ. However, this system is not + in all of the versions we support, so we simply have to cope with + this stupidity and hope that the versions we use will work itself + out... +- **On Fabric:** Fabric has a built-in dependency system (via JiJ, aka + "Jar-in-Jar"). Assuming all dependencies follow SemVer correctly + (which all of ours do), we can simply use the `include` configuration + to include the dependencies in the final JAR file, and Fabric will + automatically handle any version conflicts. +- **On NeoForge / modern Forge with JiJ:** We can use the same system as + Fabric. + +In addition, the `UniversalCraft` library is per-MC version, adding a new +level of complexity, LWJGL is split between LWJGL2 (1.12 and below) and +LWJGL3 (1.13 and above), and we require the `PolyMixin` library for +1.12.2 and below. + +## So... what do we do? + +- **On Legacy Forge:** We put all of our dependencies packed into separate + JAR into one singular JAR file. Once the OneConfig loader downloads the + dependency JAR, it will extract the JAR and load / handle each individual + JAR / dependency from there. +- **On modern Forge without JiJ:** We shade all of our dependencies into + the platform JAR and pray that it works. +- **On Fabric:** We use the `include` configuration to include the + dependencies in the final JAR file. +- **On NeoForge / modern Forge with JiJ:** We use the same system as + Fabric. \ No newline at end of file diff --git a/modules/dependencies/build.gradle.kts b/modules/dependencies/build.gradle.kts index 0b07b149c..94376640d 100644 --- a/modules/dependencies/build.gradle.kts +++ b/modules/dependencies/build.gradle.kts @@ -1,5 +1,3 @@ -description = "Shared external libraries and dependencies" - allprojects { with(tasks) { arrayOf("javadocJar", "sourcesJar").forEach { @@ -11,17 +9,4 @@ allprojects { repositories { mavenLocal() maven("https://repo.polyfrost.org/snapshots") -} - -dependencies { - api(libs.polyui) - - api(libs.bundles.kotlin) - api(libs.bundles.kotlinx) - - api(libs.hypixel.modapi) - - api(libs.bundles.nightconfig) - - api(libs.isolated.lwjgl3.loader) } \ No newline at end of file diff --git a/modules/dependencies/legacy/build.gradle.kts b/modules/dependencies/legacy/build.gradle.kts index b255ff8ea..3f3fd9eb6 100644 --- a/modules/dependencies/legacy/build.gradle.kts +++ b/modules/dependencies/legacy/build.gradle.kts @@ -1,16 +1,17 @@ +import org.polyfrost.gradle.provideIncludedDependencies + plugins { - alias(libs.plugins.jetbrains.idea.ext) + id("org.polyfrost.loom") } -description = "Dependencies for legacy platforms (<1.12)" - -val natives = listOf("windows", "windows-arm64", "linux", "macos", "macos-arm64") - dependencies { - for (dep in listOf("-nanovg", "-tinyfd", "-stb", "")) { - val lwjglDep = "org.lwjgl:lwjgl$dep:${libs.versions.lwjgl.get()}" - api(lwjglDep) { - isTransitive = false + minecraft("com.mojang:minecraft:1.16.5") + mappings("net.fabricmc:yarn:1.16.5+build.10:v2") + + provideIncludedDependencies(null, "forge").forEach { + val dep = if (it.mod) modCompileOnly(it.dep) else compileOnly(it.dep) + if (dep != null) { + include(dep) } } } \ No newline at end of file diff --git a/modules/dependencies/legacy/src/main/resources/fabric.mod.json b/modules/dependencies/legacy/src/main/resources/fabric.mod.json new file mode 100644 index 000000000..c349d9f80 --- /dev/null +++ b/modules/dependencies/legacy/src/main/resources/fabric.mod.json @@ -0,0 +1,22 @@ +{ + "schemaVersion": 1, + "id": "oneconfig-deps", + "name": "OneConfig Dependencies", + "version": "${version}", + "description": "Fake Fabric mod JSON for Legacy Forge mods", + "authors": [ + "Polyfrost" + ], + "contact": { + "homepage": "https://polyfrost.org", + "sources": "https://github.com/Polyfrost/OneConfig", + "issues": "https://inv.wtf/polyfrost" + }, + "license": "LGPL-3.0", + "environment": "client", + "custom": { + "modmenu": { + "badges": [ "library" ] + } + } +} \ No newline at end of file diff --git a/modules/dependencies/modern/build.gradle.kts b/modules/dependencies/modern/build.gradle.kts deleted file mode 100644 index eb6e4bdfc..000000000 --- a/modules/dependencies/modern/build.gradle.kts +++ /dev/null @@ -1,9 +0,0 @@ -description = "Dependencies for modern platforms (1.13+)" - -val natives = listOf("windows", "windows-arm64", "linux", "macos", "macos-arm64") - -dependencies { - implementation(libs.lwjgl.nvg) { - isTransitive = false - } -} \ No newline at end of file diff --git a/modules/root.gradle.kts b/modules/root.gradle.kts index 69b9dc23f..96b9c7287 100644 --- a/modules/root.gradle.kts +++ b/modules/root.gradle.kts @@ -107,6 +107,5 @@ apiValidation { ignoredProjects.add("internal") ignoredProjects.add("dependencies") ignoredProjects.add("legacy") - ignoredProjects.add("modern") ignoredProjects.add("bundled") } diff --git a/settings.gradle.kts b/settings.gradle.kts index fbab1ac6a..1312bfd06 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -55,7 +55,6 @@ listOf( "internal", "dependencies", "dependencies:legacy", - "dependencies:modern", "dependencies:bundled", "utils" ).forEach { module -> diff --git a/versions/build.gradle.kts b/versions/build.gradle.kts index 5a0856fd1..3b8599e33 100644 --- a/versions/build.gradle.kts +++ b/versions/build.gradle.kts @@ -1,6 +1,8 @@ @file:Suppress("UnstableApiUsage") // Shared build logic for all versions of OneConfig. +import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency +import org.polyfrost.gradle.provideIncludedDependencies import org.polyfrost.gradle.util.noServerRunConfigs import java.text.SimpleDateFormat @@ -41,26 +43,32 @@ loom { } repositories { - mavenLocal() maven("https://repo.polyfrost.org/releases") maven("https://repo.polyfrost.org/snapshots") } +val shadow by configurations.creating + dependencies { compileOnly("gg.essential:vigilance-1.8.9-forge:295") { isTransitive = false } - modApi("org.polyfrost:universalcraft-$platform:${libs.versions.universalcraft.get()}") { - isTransitive = false + provideIncludedDependencies(Triple(platform.mcMajor, platform.mcMinor, platform.mcPatch), platform.loaderStr).forEach { + if (it.dep is String) { + shade(it.dep as String, it.mod) + } else { + shade(it.dep as ExternalModuleDependency, it.mod) + } } - if (platform.isLegacyForge || platform.isLegacyFabric) { - implementation(project(":modules:dependencies:legacy")) - } else { - implementation(project(":modules:dependencies:modern")) + for (dep in listOf("-nanovg").run { if (platform.mcVersion < 11300) this else this + listOf("-tinyfd", "-stb", "") }) { + val lwjglDep = "org.lwjgl:lwjgl$dep:${libs.versions.lwjgl.get()}" + compileOnlyApi(lwjglDep) { + isTransitive = false + } } - implementation(project(":modules:dependencies")) + implementation(project(":modules:dependencies:bundled")) implementation(project(":modules:internal")) { isTransitive = false @@ -86,6 +94,29 @@ dependencies { } } +fun DependencyHandlerScope.shade(dependency: String, isMod: Boolean = false) { + val dep = project.dependencies.create(dependency) as ExternalModuleDependency + shade(dep, isMod) +} + +fun DependencyHandlerScope.shade(dependency: Provider, isMod: Boolean = false) { + shade(dependency.get(), isMod) +} + +fun DependencyHandlerScope.shade(dependency: ExternalModuleDependency, isMod: Boolean = false) { + val dep = "${dependency.group}:${dependency.name}:${dependency.version}" + val configuration = if (isMod) modApi(dep) { + isTransitive = false + } else api(dep) { + isTransitive = false + } + if (platform.isFabric || platform.mcVersion >= 11900) { + include(configuration) + } else if (!platform.isLegacyForge) { + shadow(configuration) + } +} + tasks { withType(Jar::class) { duplicatesStrategy = DuplicatesStrategy.EXCLUDE @@ -116,7 +147,10 @@ tasks { } } } - + remapJar { + from(shadow.files.map { zipTree(it) }) + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + } processResources { inputs.property("id", rootProject.properties["mod_id"].toString()) inputs.property("name", rootProject.name) diff --git a/versions/src/main/java/org/polyfrost/oneconfig/internal/OneConfigMixinInit.java b/versions/src/main/java/org/polyfrost/oneconfig/internal/OneConfigMixinInit.java index 87d923dda..ede347bfe 100644 --- a/versions/src/main/java/org/polyfrost/oneconfig/internal/OneConfigMixinInit.java +++ b/versions/src/main/java/org/polyfrost/oneconfig/internal/OneConfigMixinInit.java @@ -26,9 +26,9 @@ package org.polyfrost.oneconfig.internal; +import org.objectweb.asm.tree.ClassNode; import org.polyfrost.oneconfig.api.platform.v1.LoaderPlatform; import org.polyfrost.oneconfig.api.platform.v1.Platform; -import org.spongepowered.asm.lib.tree.ClassNode; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinInfo;