From 867cf6da05c56ea5ead21533a6bfdebc601e60bf Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 19 Mar 2024 23:05:30 +0100 Subject: [PATCH] Feature: JiJ dependencies on modded platforms (#4502) * Use JiJ inclusion for Fabric/NeoForge to prevent mod conflicts. Further: Don't publish shadow jars to maven. * Shade and relocate dependencies that don't conform to SemVer on Fabric * Shade/Relocate dependencies on Fabric to avoid version warnings * Use relocate function from the build-logic plugin --- bootstrap/bungeecord/build.gradle.kts | 2 +- bootstrap/mod/fabric/build.gradle.kts | 41 +++++++++-- bootstrap/mod/neoforge/build.gradle.kts | 19 +++-- bootstrap/spigot/build.gradle.kts | 17 ++--- bootstrap/velocity/build.gradle.kts | 2 + bootstrap/viaproxy/build.gradle.kts | 2 + build-logic/src/main/kotlin/extensions.kt | 15 ++-- .../geyser.modded-conventions.gradle.kts | 72 +++++++++++++------ .../geyser.publish-conventions.gradle.kts | 6 ++ .../geyser.shadow-conventions.gradle.kts | 1 - 10 files changed, 117 insertions(+), 60 deletions(-) diff --git a/bootstrap/bungeecord/build.gradle.kts b/bootstrap/bungeecord/build.gradle.kts index 4025569dd..1b57ffa5a 100644 --- a/bootstrap/bungeecord/build.gradle.kts +++ b/bootstrap/bungeecord/build.gradle.kts @@ -1,7 +1,7 @@ dependencies { api(projects.core) - implementation(libs.adventure.text.serializer.bungeecord) + compileOnlyApi(libs.bungeecord.proxy) } platformRelocate("net.md_5.bungee.jni") diff --git a/bootstrap/mod/fabric/build.gradle.kts b/bootstrap/mod/fabric/build.gradle.kts index dac042ad7..eb28e0e93 100644 --- a/bootstrap/mod/fabric/build.gradle.kts +++ b/bootstrap/mod/fabric/build.gradle.kts @@ -7,6 +7,8 @@ architectury { fabric() } +val includeTransitive: Configuration = configurations.getByName("includeTransitive") + dependencies { modImplementation(libs.fabric.loader) modApi(libs.fabric.api) @@ -15,14 +17,29 @@ dependencies { shadow(project(path = ":mod", configuration = "transformProductionFabric")) { isTransitive = false } - shadow(projects.core) { - exclude(group = "com.google.guava", module = "guava") - exclude(group = "com.google.code.gson", module = "gson") - exclude(group = "org.slf4j") - exclude(group = "com.nukkitx.fastutil") - exclude(group = "io.netty.incubator") - } + shadow(projects.core) { isTransitive = false } + includeTransitive(projects.core) + // These are NOT transitively included, and instead shadowed + relocated. + // Avoids fabric complaining about non-SemVer versioning + // TODO: re-evaluate after loom 1.6 (https://github.com/FabricMC/fabric-loom/pull/1075) + shadow(libs.protocol.connection) { isTransitive = false } + shadow(libs.protocol.common) { isTransitive = false } + shadow(libs.protocol.codec) { isTransitive = false } + shadow(libs.mcauthlib) { isTransitive = false } + shadow(libs.raknet) { isTransitive = false } + shadow(libs.netty.codec.haproxy) { isTransitive = false } + shadow("org.cloudburstmc:nbt:3.0.2.Final") { isTransitive = false } + shadow("io.netty:netty-codec-dns:4.1.103.Final") { isTransitive = false } + shadow("io.netty:netty-resolver-dns-classes-macos:4.1.103.Final") { isTransitive = false } + + // Consequences of shading + relocating mcauthlib: shadow/relocate mcpl! + shadow(libs.mcprotocollib) { isTransitive = false } + + // Since we also relocate cloudburst protocol: shade erosion common + shadow(libs.erosion.common) { isTransitive = false } + + // Permissions modImplementation(libs.fabric.permissions) include(libs.fabric.permissions) } @@ -31,6 +48,16 @@ application { mainClass.set("org.geysermc.geyser.platform.fabric.GeyserFabricMain") } +relocate("org.cloudburstmc.nbt") +relocate("org.cloudburstmc.netty") +relocate("org.cloudburstmc.protocol") +relocate("io.netty.handler.codec.dns") +relocate("io.netty.handler.codec.haproxy") +relocate("io.netty.resolver.dns.macos") +relocate("com.github.steveice10.mc.protocol") +relocate("com.github.steveice10.mc.auth") +relocate("com.github.steveice10.packetlib") + tasks { remapJar { archiveBaseName.set("Geyser-Fabric") diff --git a/bootstrap/mod/neoforge/build.gradle.kts b/bootstrap/mod/neoforge/build.gradle.kts index d85087542..2a414e6dd 100644 --- a/bootstrap/mod/neoforge/build.gradle.kts +++ b/bootstrap/mod/neoforge/build.gradle.kts @@ -2,11 +2,17 @@ plugins { application } +// This is provided by "org.cloudburstmc.math.mutable" too, so yeet. +// NeoForge's class loader is *really* annoying. +provided("org.cloudburstmc.math", "api") + architectury { platformSetupLoomIde() neoForge() } +val includeTransitive: Configuration = configurations.getByName("includeTransitive") + dependencies { // See https://github.com/google/guava/issues/6618 modules { @@ -21,12 +27,9 @@ dependencies { shadow(project(path = ":mod", configuration = "transformProductionNeoForge")) { isTransitive = false } - shadow(projects.core) { - exclude(group = "com.google.guava", module = "guava") - exclude(group = "com.google.code.gson", module = "gson") - exclude(group = "org.slf4j") - exclude(group = "io.netty.incubator") - } + shadow(project(path = ":core")) { isTransitive = false } + + includeTransitive(projects.core) } application { @@ -34,10 +37,6 @@ application { } tasks { - shadowJar { - relocate("it.unimi.dsi.fastutil", "org.geysermc.relocate.fastutil") - } - remapJar { archiveBaseName.set("Geyser-NeoForge") } diff --git a/bootstrap/spigot/build.gradle.kts b/bootstrap/spigot/build.gradle.kts index 129064cd4..41da1a0de 100644 --- a/bootstrap/spigot/build.gradle.kts +++ b/bootstrap/spigot/build.gradle.kts @@ -11,18 +11,11 @@ dependencies { implementation(libs.commodore) implementation(libs.adventure.text.serializer.bungeecord) - - // Both folia-api and paper-mojangapi only provide Java 17 versions for 1.19 - compileOnly(libs.folia.api) { - attributes { - attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17) - } - } - compileOnly(libs.paper.mojangapi) { - attributes { - attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17) - } - } + + compileOnly(libs.folia.api) + compileOnly(libs.paper.mojangapi) + + compileOnlyApi(libs.viaversion) } platformRelocate("it.unimi.dsi.fastutil") diff --git a/bootstrap/velocity/build.gradle.kts b/bootstrap/velocity/build.gradle.kts index 8908b2afd..a21fb2349 100644 --- a/bootstrap/velocity/build.gradle.kts +++ b/bootstrap/velocity/build.gradle.kts @@ -1,6 +1,8 @@ dependencies { annotationProcessor(libs.velocity.api) api(projects.core) + + compileOnlyApi(libs.velocity.api) } platformRelocate("com.fasterxml.jackson") diff --git a/bootstrap/viaproxy/build.gradle.kts b/bootstrap/viaproxy/build.gradle.kts index 4d5d4f949..01c5b5b34 100644 --- a/bootstrap/viaproxy/build.gradle.kts +++ b/bootstrap/viaproxy/build.gradle.kts @@ -1,5 +1,7 @@ dependencies { api(projects.core) + + compileOnlyApi(libs.viaproxy) } platformRelocate("net.kyori") diff --git a/build-logic/src/main/kotlin/extensions.kt b/build-logic/src/main/kotlin/extensions.kt index b4a14f678..41e11344b 100644 --- a/build-logic/src/main/kotlin/extensions.kt +++ b/build-logic/src/main/kotlin/extensions.kt @@ -58,19 +58,20 @@ fun Project.platformRelocate(pattern: String, exclusion: String = "") { val providedDependencies = mutableMapOf>() -fun Project.provided(pattern: String, name: String, version: String, excludedOn: Int = 0b110) { +fun getProvidedDependenciesForProject(projectName: String): MutableSet { + return providedDependencies.getOrDefault(projectName, emptySet()).toMutableSet() +} + +fun Project.provided(pattern: String, name: String, excludedOn: Int = 0b110) { providedDependencies.getOrPut(project.name) { mutableSetOf() } - .add("${calcExclusion(pattern, 0b100, excludedOn)}:" + - "${calcExclusion(name, 0b10, excludedOn)}:" + - calcExclusion(version, 0b1, excludedOn)) - dependencies.add("compileOnlyApi", "$pattern:$name:$version") + .add("${calcExclusion(pattern, 0b100, excludedOn)}:${calcExclusion(name, 0b10, excludedOn)}") } fun Project.provided(dependency: ProjectDependency) = - provided(dependency.group!!, dependency.name, dependency.version!!) + provided(dependency.group!!, dependency.name) fun Project.provided(dependency: MinimalExternalModuleDependency) = - provided(dependency.module.group, dependency.module.name, dependency.versionConstraint.requiredVersion) + provided(dependency.module.group, dependency.module.name) fun Project.provided(provider: Provider) = provided(provider.get()) diff --git a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts index 0842eae84..91bde525e 100644 --- a/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.modded-conventions.gradle.kts @@ -11,6 +11,31 @@ plugins { id("com.modrinth.minotaur") } +// These are provided by Minecraft/modded platforms already, no need to include them +provided("com.google.code.gson", "gson") +provided("com.google.guava", ".*") +provided("org.slf4j", "slf4j-api") +provided("com.nukkitx.fastutil", ".*") +provided("org.cloudburstmc.fastutil.maps", ".*") +provided("org.cloudburstmc.fastutil.sets", ".*") +provided("org.cloudburstmc.fastutil.commons", ".*") +provided("org.cloudburstmc.fastutil", ".*") +provided("org.checkerframework", "checker-qual") +provided("io.netty", "netty-transport-classes-epoll") +provided("io.netty", "netty-transport-native-epoll") +provided("io.netty", "netty-transport-native-unix-common") +provided("io.netty", "netty-transport-classes-kqueue") +provided("io.netty", "netty-transport-native-kqueue") +provided("io.netty", "netty-handler") +provided("io.netty", "netty-common") +provided("io.netty", "netty-buffer") +provided("io.netty", "netty-resolver") +provided("io.netty", "netty-transport") +provided("io.netty", "netty-codec") +provided("io.netty", "netty-resolver-dns") +provided("io.netty", "netty-resolver-dns-native-macos") +provided("org.ow2.asm", "asm") + architectury { minecraft = "1.20.4" } @@ -19,6 +44,10 @@ loom { silentMojangMappingsLicense() } +configurations { + create("includeTransitive").isTransitive = true +} + tasks { // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task // if it is present. @@ -34,28 +63,6 @@ tasks { // The remapped shadowJar is the final desired mod jar archiveVersion.set(project.version.toString()) archiveClassifier.set("shaded") - - relocate("org.objectweb.asm", "org.geysermc.relocate.asm") - relocate("org.yaml", "org.geysermc.relocate.yaml") // https://github.com/CardboardPowered/cardboard/issues/139 - relocate("com.fasterxml.jackson", "org.geysermc.relocate.jackson") - relocate("net.kyori", "org.geysermc.relocate.kyori") - - dependencies { - // Exclude everything EXCEPT some DNS stuff required for HAProxy - exclude(dependency("io.netty:netty-transport-classes-epoll:.*")) - exclude(dependency("io.netty:netty-transport-native-epoll:.*")) - exclude(dependency("io.netty:netty-transport-native-unix-common:.*")) - exclude(dependency("io.netty:netty-transport-classes-kqueue:.*")) - exclude(dependency("io.netty:netty-transport-native-kqueue:.*")) - exclude(dependency("io.netty:netty-handler:.*")) - exclude(dependency("io.netty:netty-common:.*")) - exclude(dependency("io.netty:netty-buffer:.*")) - exclude(dependency("io.netty:netty-resolver:.*")) - exclude(dependency("io.netty:netty-transport:.*")) - exclude(dependency("io.netty:netty-codec:.*")) - exclude(dependency("io.netty:netty-resolver-dns:.*")) - exclude(dependency("io.netty:netty-resolver-dns-native-macos:.*")) - } } remapJar { @@ -73,6 +80,27 @@ tasks { } } +afterEvaluate { + val providedDependencies = getProvidedDependenciesForProject(project.name) + + // These are shaded, no need to JiJ them + configurations["shadow"].dependencies.forEach {shadowed -> + println("Not including shadowed dependency: ${shadowed.group}:${shadowed.name}") + providedDependencies.add("${shadowed.group}:${shadowed.name}") + } + + // Now: Include all transitive dependencies that aren't excluded + configurations["includeTransitive"].resolvedConfiguration.resolvedArtifacts.forEach { dep -> + if (!providedDependencies.contains("${dep.moduleVersion.id.group}:${dep.moduleVersion.id.name}") + and !providedDependencies.contains("${dep.moduleVersion.id.group}:.*")) { + println("Including dependency via JiJ: ${dep.id}") + dependencies.add("include", dep.moduleVersion.id.toString()) + } else { + println("Not including ${dep.id} for ${project.name}!") + } + } +} + dependencies { minecraft("com.mojang:minecraft:1.20.4") mappings(loom.officialMojangMappings()) diff --git a/build-logic/src/main/kotlin/geyser.publish-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.publish-conventions.gradle.kts index 036ee803c..eca587721 100644 --- a/build-logic/src/main/kotlin/geyser.publish-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.publish-conventions.gradle.kts @@ -7,3 +7,9 @@ indra { publishSnapshotsTo("geysermc", "https://repo.opencollab.dev/maven-snapshots") publishReleasesTo("geysermc", "https://repo.opencollab.dev/maven-releases") } + +publishing { + // skip shadow jar from publishing. Workaround for https://github.com/johnrengelman/shadow/issues/651 + val javaComponent = project.components["java"] as AdhocComponentWithVariants + javaComponent.withVariantsFromConfiguration(configurations["shadowRuntimeElements"]) { skip() } +} \ No newline at end of file diff --git a/build-logic/src/main/kotlin/geyser.shadow-conventions.gradle.kts b/build-logic/src/main/kotlin/geyser.shadow-conventions.gradle.kts index dde85c33a..c160e5ec6 100644 --- a/build-logic/src/main/kotlin/geyser.shadow-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/geyser.shadow-conventions.gradle.kts @@ -7,7 +7,6 @@ plugins { tasks { named("jar") { - archiveClassifier.set("unshaded") from(project.rootProject.file("LICENSE")) } val shadowJar = named("shadowJar") {