diff options
author | Linnea Gräf <nea@nea.moe> | 2023-12-10 15:43:14 +0100 |
---|---|---|
committer | Linnea Gräf <nea@nea.moe> | 2023-12-10 15:43:14 +0100 |
commit | 17f0faaccb0db837a64b6ce7cecff7f8ab048410 (patch) | |
tree | d6dcd51e43d16873c14a696c565c0c343440b19e | |
parent | 67bf79815ec27c8b813480c11a45f35ef502fe5b (diff) | |
download | archenemy-17f0faaccb0db837a64b6ce7cecff7f8ab048410.tar.gz archenemy-17f0faaccb0db837a64b6ce7cecff7f8ab048410.tar.bz2 archenemy-17f0faaccb0db837a64b6ce7cecff7f8ab048410.zip |
Add crude mappings/transformer support
8 files changed, 232 insertions, 17 deletions
diff --git a/archenemyexample/build.gradle.kts b/archenemyexample/build.gradle.kts index eb0d9ff..6ed1dbe 100644 --- a/archenemyexample/build.gradle.kts +++ b/archenemyexample/build.gradle.kts @@ -19,7 +19,13 @@ kotlin { compilations.named("main").get().run { defaultSourceSet.dependsOn(allJvm) this.dependencies { - implementation(mojang.minecraft("1.8.9", MCSide.CLIENT)) + val mappedMinecraft = mojang.mapJar( + mojang.minecraft("1.20.2", MCSide.CLIENT) as ModuleDependency, + mojang.officialMappings("1.20.2", MCSide.CLIENT), + "official", + "named" + ) + implementation(mappedMinecraft) } } } diff --git a/archenemyexample/src/forgeMain/kotlin/doStuff.kt b/archenemyexample/src/forgeMain/kotlin/doStuff.kt index 659bc2b..1e773ef 100644 --- a/archenemyexample/src/forgeMain/kotlin/doStuff.kt +++ b/archenemyexample/src/forgeMain/kotlin/doStuff.kt @@ -1,3 +1,3 @@ actual fun doStuff(args: Int) { - + val x: a = TODO() }
\ No newline at end of file diff --git a/plugin/src/main/kotlin/moe/nea/archenemy/mojang/ArchenemyMojangExtension.kt b/plugin/src/main/kotlin/moe/nea/archenemy/mojang/ArchenemyMojangExtension.kt index b3b3cfd..b80fe89 100644 --- a/plugin/src/main/kotlin/moe/nea/archenemy/mojang/ArchenemyMojangExtension.kt +++ b/plugin/src/main/kotlin/moe/nea/archenemy/mojang/ArchenemyMojangExtension.kt @@ -4,6 +4,8 @@ import moe.nea.archenemy.MCSide import net.minecraftforge.artifactural.gradle.GradleRepositoryAdapter import org.gradle.api.Project import org.gradle.api.artifacts.Dependency +import org.gradle.api.artifacts.ModuleDependency +import java.io.File import java.net.URI abstract class ArchenemyMojangExtension(val project: Project) { @@ -16,12 +18,51 @@ abstract class ArchenemyMojangExtension(val project: Project) { sharedExtension.getLocalCacheDirectory().resolve("minecraft-provider"), sharedExtension.minecraftProvider ) + GradleRepositoryAdapter.add( + project.repositories, + "Minecraft Mapped Provider", + getLocalCacheDirectory().resolve("minecraft-transformation-provider"), + mappedRepositoryProvider + ) project.repositories.maven { it.name = "Minecraft Libraries" it.url = URI("https://libraries.minecraft.net/") } } + private val mappedRepositoryProvider = MappedRepositoryProvider(this) + + + fun officialMappings(version: String, side: MCSide): MappingDependency { + _registerMinecraftProvider + val dependency by lazy { + project.dependencies.create( + sharedExtension.minecraftProvider.getMappingsDependencyCoordinate( + MinecraftProvider.MinecraftCoordinate( + version, + side + ) + ) + ) + } + return OfficialMappingDependency(side, version, project.providers.provider { dependency }) + } + + fun mapJar( + dependency: ModuleDependency, + mappings: MappingDependency, + sourceNamespace: String, + destinationNamespace: String + ): Dependency { + _registerMinecraftProvider + return project.dependencies.create( + mappedRepositoryProvider.getDependencyCoordiante( + MappedRepositoryProvider.MappedCoordinates( + dependency, mappings, sourceNamespace, destinationNamespace + ) + ) + ) + } fun minecraft(version: String, side: MCSide): Dependency { _registerMinecraftProvider @@ -35,4 +76,9 @@ abstract class ArchenemyMojangExtension(val project: Project) { ) } + fun getLocalCacheDirectory(): File { + return sharedExtension.getLocalCacheDirectory().resolve("projectspecific") + .resolve(if (project == project.rootProject) "__root" else project.path.replace(":", "_")) + } + }
\ No newline at end of file diff --git a/plugin/src/main/kotlin/moe/nea/archenemy/mojang/MappedRepositoryProvider.kt b/plugin/src/main/kotlin/moe/nea/archenemy/mojang/MappedRepositoryProvider.kt new file mode 100644 index 0000000..d176d45 --- /dev/null +++ b/plugin/src/main/kotlin/moe/nea/archenemy/mojang/MappedRepositoryProvider.kt @@ -0,0 +1,99 @@ +package moe.nea.archenemy.mojang + +import moe.nea.archenemy.DownloadUtils +import moe.nea.archenemy.util.getNullsafeIdentifier +import net.minecraftforge.artifactural.api.artifact.Artifact +import net.minecraftforge.artifactural.api.artifact.ArtifactIdentifier +import net.minecraftforge.artifactural.api.artifact.ArtifactType +import net.minecraftforge.artifactural.api.repository.Repository +import net.minecraftforge.artifactural.base.artifact.StreamableArtifact +import org.gradle.api.artifacts.ModuleDependency +import java.security.MessageDigest + +class MappedRepositoryProvider( + val sharedExtension: ArchenemyMojangExtension +) : Repository { + + data class MappedCoordinates( + val dependency: ModuleDependency, + val mappings: MappingDependency, + val from: String, + val to: String, + ) { + val transformerHash by lazy { + val messageDigest = MessageDigest.getInstance("SHA-256") + messageDigest.updateField("name", dependency.name) + messageDigest.updateField("from", from) + messageDigest.updateField("to", to) + messageDigest.updateField("version", dependency.version ?: "null") + messageDigest.updateField("group", dependency.group ?: "null") + mappings.updateHash(messageDigest) + DownloadUtils.bytesToHex(messageDigest.digest()) + } + } + + private val providers = mutableMapOf<String, MappedCoordinates>() + private val cacheDir = sharedExtension.getLocalCacheDirectory().resolve("minecraft-transformer-cache") + + + fun getDependencyCoordiante(coordinates: MappedCoordinates): String { + providers[coordinates.transformerHash] = coordinates + return "archenemy.remapped.${coordinates.transformerHash}.${coordinates.mappings.title()}-${coordinates.to}.${coordinates.dependency.group}:${coordinates.dependency.name}:${coordinates.dependency.version}" + } + + fun getDependencyCoordiante( + dependency: ModuleDependency, + mappings: MappingDependency, + from: String, + to: String + ): String { + val coordinates = MappedCoordinates(dependency, mappings, from, to) + return getDependencyCoordiante(coordinates) + } + + + override fun getArtifact(identifier: ArtifactIdentifier?): Artifact { + if (identifier == null) return Artifact.none() + if (!identifier.group.startsWith("archenemy.remapped.")) return Artifact.none() + if (identifier.extension != "jar") return Artifact.none() // TODO: support other artifacts (and poms) + val hash = identifier.group.split(".")[2] + val coordinates = providers[hash] ?: error("Unregistered mapped dependency $identifier") + val (group, name, version) = getDependencyCoordiante(coordinates).split(":") + if (group != identifier.group || name != identifier.name || version != identifier.version) + error("Inconsistent mapped dependency $identifier (expected $coordinates)") + + return getArtifact(coordinates, getNullsafeIdentifier(identifier)) ?: Artifact.none() + } + + private fun getArtifact(coordinates: MappedCoordinates, identifier: ArtifactIdentifier): Artifact? { + if ((identifier.classifier ?: "") != "") return null + val files = sharedExtension.project.configurations.detachedConfiguration( + coordinates.dependency, + coordinates.mappings.get() + ).also { it.isTransitive = false }.resolve() + // TODO: move away from classifiers. those are *evil*. + // for now i will just manually append -client + // or figure out how loom does it, i suppose + val sourceName = listOfNotNull( + coordinates.dependency.name, + coordinates.dependency.version, + coordinates.dependency.artifacts.single().classifier + ).joinToString(separator = "-", postfix = ".jar") + val sourceFile = files.singleOrNull { it.name == sourceName } ?: return null + val mappingsFile = coordinates.mappings.findMapping(files) ?: error("Could not find mappings file") + val targetFile = cacheDir.resolve(coordinates.transformerHash + ".jar") + targetFile.parentFile.mkdirs() + return StreamableArtifact.ofStreamable(identifier, ArtifactType.BINARY) { + if (!targetFile.exists()) { + coordinates.mappings.applyMapping( + mappingsFile = mappingsFile, + sourceFile = sourceFile, + targetFile = targetFile, + sourceNameSpace = coordinates.from, + targetNameSpace = coordinates.to + ) + } + targetFile.inputStream() + } + } +}
\ No newline at end of file diff --git a/plugin/src/main/kotlin/moe/nea/archenemy/mojang/MappingDependency.kt b/plugin/src/main/kotlin/moe/nea/archenemy/mojang/MappingDependency.kt new file mode 100644 index 0000000..a0e1b14 --- /dev/null +++ b/plugin/src/main/kotlin/moe/nea/archenemy/mojang/MappingDependency.kt @@ -0,0 +1,19 @@ +package moe.nea.archenemy.mojang + +import org.gradle.api.artifacts.Dependency +import org.gradle.api.provider.Provider +import java.io.File +import java.security.MessageDigest + +interface MappingDependency : Provider<Dependency> { + fun updateHash(digest: MessageDigest) + fun title(): String + fun findMapping(files: Set<File>): File? + fun applyMapping( + mappingsFile: File, + sourceFile: File, + targetFile: File, + sourceNameSpace: String, + targetNameSpace: String, + ) +}
\ No newline at end of file diff --git a/plugin/src/main/kotlin/moe/nea/archenemy/mojang/MinecraftProvider.kt b/plugin/src/main/kotlin/moe/nea/archenemy/mojang/MinecraftProvider.kt index 845d3e7..64c1d04 100644 --- a/plugin/src/main/kotlin/moe/nea/archenemy/mojang/MinecraftProvider.kt +++ b/plugin/src/main/kotlin/moe/nea/archenemy/mojang/MinecraftProvider.kt @@ -4,6 +4,7 @@ import kotlinx.serialization.json.Json import kotlinx.serialization.json.decodeFromStream import moe.nea.archenemy.DownloadUtils import moe.nea.archenemy.MCSide +import moe.nea.archenemy.util.getNullsafeIdentifier import net.minecraftforge.artifactural.api.artifact.Artifact import net.minecraftforge.artifactural.api.artifact.ArtifactIdentifier import net.minecraftforge.artifactural.api.artifact.ArtifactType @@ -29,7 +30,6 @@ fun MessageDigest.update(text: String) { class MinecraftProvider(val sharedExtension: ArchenemySharedExtension) : Repository { - data class MinecraftCoordinate( val version: String, val side: MCSide, @@ -74,7 +74,7 @@ class MinecraftProvider(val sharedExtension: ArchenemySharedExtension) : Reposit val downloadType = when (coordinate.side) { MCSide.CLIENT -> "client" MCSide.SERVER -> "server" - } + if (mappings) "-mappings" else "" + } + if (mappings) "_mappings" else "" val download = metadata.downloads[downloadType] ?: throw IOException("Invalid minecraft side $downloadType for ${coordinate.version}") val targetFile = @@ -96,21 +96,11 @@ class MinecraftProvider(val sharedExtension: ArchenemySharedExtension) : Reposit } } - fun getNullsafeIdentifier(identifier: ArtifactIdentifier): ArtifactIdentifier { - return object : ArtifactIdentifier by identifier { - override fun getClassifier(): String { - return if (identifier.classifier == null) - "" - else - identifier.classifier - } - } - } override fun getArtifact(identifier: ArtifactIdentifier?): Artifact { if (identifier == null) return Artifact.none() if (identifier.name != "minecraft") return Artifact.none() - if (!identifier.group.startsWith("archenemy.")) return Artifact.none() + if (identifier.group != "archenemy.mojang") return Artifact.none() if (identifier.extension == "pom") return Artifact.none() val coordinate = MinecraftCoordinate(identifier.version, MCSide.valueOf(identifier.classifier.removeSuffix("-mappings"))) @@ -133,6 +123,5 @@ class MinecraftProvider(val sharedExtension: ArchenemySharedExtension) : Reposit } return Artifact.none() } +} - -}
\ No newline at end of file diff --git a/plugin/src/main/kotlin/moe/nea/archenemy/mojang/OfficialMappingDependency.kt b/plugin/src/main/kotlin/moe/nea/archenemy/mojang/OfficialMappingDependency.kt new file mode 100644 index 0000000..8617ede --- /dev/null +++ b/plugin/src/main/kotlin/moe/nea/archenemy/mojang/OfficialMappingDependency.kt @@ -0,0 +1,42 @@ +package moe.nea.archenemy.mojang + +import moe.nea.archenemy.MCSide +import org.gradle.api.artifacts.Dependency +import org.gradle.api.provider.Provider +import java.io.File +import java.security.MessageDigest + +class OfficialMappingDependency( + val side: MCSide, + val version: String, + val dependency: Provider<Dependency> +) : MappingDependency, + Provider<Dependency> by dependency { + + override fun updateHash(digest: MessageDigest) { + digest.update("official") + digest.updateField("side", side.toString()) + digest.updateField("version", version) + } + + override fun title(): String { + return "official-$side-${version.replace(".","_")}" + } + + override fun findMapping(files: Set<File>): File? { + return files.singleOrNull { + it.name == "minecraft-${version}-${side}-mappings.txt" + } + } + + override fun applyMapping( + mappingsFile: File, + sourceFile: File, + targetFile: File, + sourceNameSpace: String, + targetNameSpace: String + ) { + sourceFile.copyTo(targetFile) + } + +}
\ No newline at end of file diff --git a/plugin/src/main/kotlin/moe/nea/archenemy/util/GetNullsafeIdentifier.kt b/plugin/src/main/kotlin/moe/nea/archenemy/util/GetNullsafeIdentifier.kt new file mode 100644 index 0000000..9d9a422 --- /dev/null +++ b/plugin/src/main/kotlin/moe/nea/archenemy/util/GetNullsafeIdentifier.kt @@ -0,0 +1,14 @@ +package moe.nea.archenemy.util + +import net.minecraftforge.artifactural.api.artifact.ArtifactIdentifier + +fun getNullsafeIdentifier(identifier: ArtifactIdentifier): ArtifactIdentifier { + return object : ArtifactIdentifier by identifier { + override fun getClassifier(): String { + return if (identifier.classifier == null) + "" + else + identifier.classifier + } + } +}
\ No newline at end of file |