diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bf9673533..eb5618af8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,7 +24,7 @@ jobs: git config --global user.name "GitHub Actions" ./gradlew build --no-daemon --stacktrace - name: Publish Test Report - uses: mikepenz/action-junit-report@v5 + uses: mikepenz/action-junit-report@v6 if: always() with: report_paths: '**/build/test-results/test/TEST-*.xml' diff --git a/buildSrc/src/main/kotlin/config-kotlin.gradle.kts b/buildSrc/src/main/kotlin/config-kotlin.gradle.kts index d79cda011..9f3b815b8 100644 --- a/buildSrc/src/main/kotlin/config-kotlin.gradle.kts +++ b/buildSrc/src/main/kotlin/config-kotlin.gradle.kts @@ -64,9 +64,9 @@ testing { val test by getting(JvmTestSuite::class) { useKotlinTest(embeddedKotlinVersion) dependencies { - implementation("org.junit.jupiter:junit-jupiter-engine:6.0.0") - implementation("org.junit.jupiter:junit-jupiter-params:6.0.0") - implementation("org.junit.platform:junit-platform-launcher:6.0.0") + implementation("org.junit.jupiter:junit-jupiter-engine:6.0.3") + implementation("org.junit.jupiter:junit-jupiter-params:6.0.3") + implementation("org.junit.platform:junit-platform-launcher:6.0.3") } targets.configureEach { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e3785edb9..4c481a7b5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -asm = "9.9" +asm = "9.9.1" lorenz = "0.5.8" hypo = "1.2.4" serialize = "1.9.0" @@ -44,13 +44,13 @@ jst = { module = "io.canvasmc.jst:jst-cli-bundle", version.ref = "jst" } tinyRemapper = { module = "net.fabricmc:tiny-remapper", version.ref = "tinyRemapper" } # test -mockk = "io.mockk:mockk:1.14.6" +mockk = "io.mockk:mockk:1.14.9" # Gradle gradle-licenser = "net.kyori:indra-licenser-spotless:4.0.0" gradle-spotless = "com.diffplug.spotless:spotless-plugin-gradle:8.0.0" -gradle-shadow = "com.gradleup.shadow:com.gradleup.shadow.gradle.plugin:9.2.2" -gradle-kotlin-dsl = "org.gradle.kotlin.kotlin-dsl:org.gradle.kotlin.kotlin-dsl.gradle.plugin:6.2.0" +gradle-shadow = "com.gradleup.shadow:com.gradleup.shadow.gradle.plugin:9.3.2" +gradle-kotlin-dsl = "org.gradle.kotlin.kotlin-dsl:org.gradle.kotlin.kotlin-dsl.gradle.plugin:6.4.2" gradle-plugin-kotlin = { module = "org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin" } gradle-plugin-publish = "com.gradle.publish:plugin-publish-plugin:2.0.0" diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 8bdaf60c7..61285a659 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a35649f5f..5f38436fc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/PaperweightCore.kt b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/PaperweightCore.kt index 3977abebc..2c2d799b0 100644 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/PaperweightCore.kt +++ b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/PaperweightCore.kt @@ -34,7 +34,6 @@ import io.papermc.paperweight.core.tasks.patching.ApplyFilePatches import io.papermc.paperweight.core.tasks.patching.RebuildFilePatches import io.papermc.paperweight.core.tasks.patchroulette.PatchRouletteTasks import io.papermc.paperweight.core.util.coreExt -import io.papermc.paperweight.core.util.createBuildTasks import io.papermc.paperweight.tasks.* import io.papermc.paperweight.util.* import io.papermc.paperweight.util.constants.* @@ -143,18 +142,7 @@ abstract class PaperweightCore : Plugin { } } - val jar = target.tasks.named("jar", AbstractArchiveTask::class) - tasks.generateReobfMappings { - inputJar.set(jar.flatMap { it.archiveFile }) - } - tasks.generateRelocatedReobfMappings { - inputJar.set(jar.flatMap { it.archiveFile }) - } - val (mappedJar, reobfJar) = target.createBuildTasks( - ext.spigot, - ext.reobfPackagesToFix, - tasks.generateRelocatedReobfMappings.flatMap { it.outputMappings }, - ) + val serverJar = target.tasks.named("jar", AbstractArchiveTask::class).flatMap { it.archiveFile } PaperclipTasks( target, @@ -163,8 +151,7 @@ abstract class PaperweightCore : Plugin { tasks.extractFromBundler.flatMap { it.versionJson }, tasks.extractFromBundler.flatMap { it.serverLibrariesList }, tasks.downloadServerJar.flatMap { it.outputJar }, - mappedJar, - reobfJar, + serverJar, ext.minecraftVersion, ext.activeFork.map { it.name }.orElse("paper") ) @@ -213,10 +200,10 @@ abstract class PaperweightCore : Plugin { tasks.afterEvaluate() devBundleTasks.configureAfterEvaluate( - mappedJar, + serverJar, ) - if (coreExt.updatingMinecraft.oldPaperCommit.isPresent) { + if (coreExt.updatingMinecraft.oldPaperCommit.isPresent || target.providers.gradleProperty("updatingMinecraft").orNull == "true") { tasks.paperPatchingTasks.applyBasePatches.configure { additionalRemote = layout.cache.resolve( "$OLD_PAPER_PATH/${coreExt.updatingMinecraft.oldPaperCommit.get()}/paper-server/src/minecraft/java" diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/extension/PaperweightCoreExtension.kt b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/extension/PaperweightCoreExtension.kt index d88de899b..f79414726 100644 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/extension/PaperweightCoreExtension.kt +++ b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/extension/PaperweightCoreExtension.kt @@ -49,21 +49,8 @@ abstract class PaperweightCoreExtension @Inject constructor(objects: ObjectFacto listOf("/*.class", "/net/minecraft/**", "/com/mojang/math/**") ) - val reobfPackagesToFix: ListProperty = objects.listProperty() - - val spigot = objects.newInstance().also { spigot -> - spigot.enabled.convention( - spigot.buildDataRef.zip(spigot.packageVersion) { ref, pkg -> ref.isNotBlank() && pkg.isNotBlank() } - .orElse(false) - ) - } val paper = objects.newInstance(project) - @Suppress("unused") - fun spigot(action: Action) { - action.execute(spigot) - } - @Suppress("unused") fun paper(action: Action) { action.execute(paper) diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/AllTasks.kt b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/AllTasks.kt index 2f790a5fc..a859c0a6b 100644 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/AllTasks.kt +++ b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/AllTasks.kt @@ -43,7 +43,7 @@ open class AllTasks( cache: Path = project.layout.cache, extension: PaperweightCoreExtension = project.coreExt, downloadService: Provider = project.download -) : SpigotTasks(project) { +) : InitialTasks(project) { val downloadMcLibrariesSources by tasks.registering { mcLibrariesFile.set(extractFromBundler.flatMap { it.serverLibrariesTxt }) @@ -74,30 +74,4 @@ open class AllTasks( downloader.set(downloadService) } - - val generateReobfMappings by tasks.registering { - inputMappings.set(patchMappings.flatMap { it.outputMappings }) - notchToSpigotMappings.set(generateSpigotMappings.flatMap { it.notchToSpigotMappings }) - sourceMappings.set(generateMappings.flatMap { it.outputMappings }) - // TODO: spigot uses javac now(?) so is this needed anymore? - // spigotRecompiledClasses.set(remapSpigotSources.flatMap { it.spigotRecompiledClasses }) - - reobfMappings.set(cache.resolve(REOBF_MOJANG_SPIGOT_MAPPINGS)) - } - - val patchReobfMappings by tasks.registering { - inputMappings.set(generateReobfMappings.flatMap { it.reobfMappings }) - patch.set(extension.paper.reobfMappingsPatch.fileExists()) - - fromNamespace.set(DEOBF_NAMESPACE) - toNamespace.set(SPIGOT_NAMESPACE) - - outputMappings.set(cache.resolve(PATCHED_REOBF_MOJANG_SPIGOT_MAPPINGS)) - } - - val generateRelocatedReobfMappings by tasks.registering { - inputMappings.set(patchReobfMappings.flatMap { it.outputMappings }) - outputMappings.set(cache.resolve(RELOCATED_PATCHED_REOBF_MOJANG_SPIGOT_MAPPINGS)) - craftBukkitPackageVersion.set(extension.spigot.packageVersion) - } } diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/CoreTasks.kt b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/CoreTasks.kt index 26d629c31..5190bc1d1 100644 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/CoreTasks.kt +++ b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/CoreTasks.kt @@ -51,13 +51,10 @@ class CoreTasks( val macheRemapJar by tasks.registering(RunCodebook::class) { serverJar.set(extractFromBundler.flatMap { it.serverJar }) - serverMappings.set(downloadMappings.flatMap { it.outputFile }) - remapperArgs.set(mache.map { it.remapperArgs }) + codebookArgs.set(mache.map { it.remapperArgs }) codebookClasspath.from(project.configurations.named(MACHE_CODEBOOK_CONFIG)) minecraftClasspath.from(project.configurations.named(MACHE_MINECRAFT_LIBRARIES_CONFIG)) - remapperClasspath.from(project.configurations.named(MACHE_REMAPPER_CONFIG)) - paramMappings.from(project.configurations.named(MACHE_PARAM_MAPPINGS_CONFIG)) constants.from(project.configurations.named(MACHE_CONSTANTS_CONFIG)) outputJar.set(layout.cache.resolve(FINAL_REMAPPED_CODEBOOK_JAR)) diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/DevBundleTasks.kt b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/DevBundleTasks.kt index 5591378d6..fa54119e1 100644 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/DevBundleTasks.kt +++ b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/DevBundleTasks.kt @@ -68,15 +68,6 @@ class DevBundleTasks( minecraftVersion.set(project.coreExt.minecraftVersion) mojangMappedPaperclipFile.set(paperclipForDevBundle.flatMap { it.outputZip }) - reobfMappingsFile.set( - project.coreExt.spigot.enabled.flatMap { - if (it) { - coreTasks.generateRelocatedReobfMappings.flatMap { t -> t.outputMappings } - } else { - null - } - } - ) } fun configureAfterEvaluate(serverJar: Provider) { diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/InitialTasks.kt b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/InitialTasks.kt index 82af6d641..54641e0f0 100644 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/InitialTasks.kt +++ b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/InitialTasks.kt @@ -71,14 +71,6 @@ open class InitialTasks( } private val versionManifest = downloadMcVersionManifest.flatMap { it.outputFile }.map { gson.fromJson(it) } - val downloadMappings by tasks.registering { - url.set(versionManifest.map { version -> version.serverMappingsDownload().url }) - expectedHash.set(versionManifest.map { version -> version.serverMappingsDownload().hash() }) - outputFile.set(cache.resolve(SERVER_MAPPINGS)) - - downloader.set(downloadService) - } - val downloadServerJar by tasks.registering { downloadUrl.set(versionManifest.map { version -> version.serverDownload().url }) expectedHash.set(versionManifest.map { version -> version.serverDownload().hash() }) @@ -96,18 +88,4 @@ open class InitialTasks( serverLibraryJars.set(cache.resolve(MINECRAFT_JARS_PATH)) serverJar.set(cache.resolve(SERVER_JAR)) } - - val filterVanillaJar by tasks.registering { - inputJar.set(extractFromBundler.flatMap { it.serverJar }) - includes.set(extension.vanillaJarIncludes) - } - - val generateMappings by tasks.registering { - vanillaJar.set(filterVanillaJar.flatMap { it.outputJar }) - libraries.from(extractFromBundler.map { it.serverLibraryJars.asFileTree }) - - vanillaMappings.set(downloadMappings.flatMap { it.outputFile }) - - outputMappings.set(cache.resolve(MOJANG_MAPPINGS)) - } } diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/PaperclipTasks.kt b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/PaperclipTasks.kt index 54da83de3..37b1a3b39 100644 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/PaperclipTasks.kt +++ b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/PaperclipTasks.kt @@ -23,7 +23,6 @@ package io.papermc.paperweight.core.taskcontainers import com.google.gson.JsonObject -import io.papermc.paperweight.core.util.reobfRequiresDebug import io.papermc.paperweight.tasks.* import io.papermc.paperweight.util.* import io.papermc.paperweight.util.constants.* @@ -46,28 +45,16 @@ class PaperclipTasks( private val bundlerVersionJson: Provider, private val serverLibrariesList: Provider, private val vanillaJar: Provider, - mojangJar: Provider, - reobfJar: Provider, + serverJar: Provider, private val mcVersion: Provider, private val forkName: Provider ) { init { - val (createBundlerJar, createPaperclipJar, createPublisherJar) = project.createTasks("mojmap") - val (createReobfBundlerJar, createReobfPaperclipJar, createReobfPublisherJar) = project.createTasks("reobf") - - createBundlerJar.serverJar(mojangJar) - createReobfBundlerJar.serverJar(reobfJar) { - reobfRequiresDebug() - } + val (createBundlerJar, createPaperclipJar, createPublisherJar) = project.createTasks() + createBundlerJar.serverJar(serverJar) createPaperclipJar.bundlerJar(createBundlerJar) - createReobfPaperclipJar.bundlerJar(createReobfBundlerJar) { - reobfRequiresDebug() - } - - createReobfPublisherJar { - reobfRequiresDebug() - } + createPublisherJar.paperclipJar(createPaperclipJar) } private fun Project.createTasks( @@ -98,7 +85,6 @@ class PaperclipTasks( group = "bundling" description = "Build a ready-to-publish paperclip jar" - inputZip.set(paperclipJarTask.flatMap { it.outputZip }) outputZip.convention(layout.buildDirectory.file(jarName("publisher", classifier).map { "libs/$it" })) } return Triple(bundlerJarTask, paperclipJarTask, publisherJarTask) @@ -115,7 +101,7 @@ class PaperclipTasks( ).joinToString("-") + ".jar" } } else { - val buildNum = project.providers.environmentVariable("BUILD_NUMBER").orElse("local") + val buildNum = providers.environmentVariable("BUILD_NUMBER").orElse("local") forkName.zip(buildNum) { name, build -> "$name-build.$build.jar" } @@ -172,6 +158,15 @@ class PaperclipTasks( op.execute(this) } + private fun TaskProvider.paperclipJar( + createPaperclipJar: TaskProvider, + op: Action = Action {}, + ) = configure { + inputZip.set(createPaperclipJar.flatMap { it.outputZip }) + + op.execute(this) + } + companion object { fun NamedDomainObjectContainer.registerVersionArtifact( name: String, diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/SpigotTasks.kt b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/SpigotTasks.kt deleted file mode 100644 index f4347f25c..000000000 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/taskcontainers/SpigotTasks.kt +++ /dev/null @@ -1,102 +0,0 @@ -/* - * paperweight is a Gradle plugin for the PaperMC project. - * - * Copyright (c) 2023 Kyle Wood (DenWav) - * Contributors - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 only, no later versions. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package io.papermc.paperweight.core.taskcontainers - -import io.papermc.paperweight.core.extension.PaperweightCoreExtension -import io.papermc.paperweight.core.util.coreExt -import io.papermc.paperweight.tasks.* -import io.papermc.paperweight.util.* -import io.papermc.paperweight.util.constants.* -import io.papermc.paperweight.util.data.* -import java.nio.file.Path -import org.gradle.api.Project -import org.gradle.api.provider.Provider -import org.gradle.api.tasks.TaskContainer -import org.gradle.kotlin.dsl.* - -@Suppress("MemberVisibilityCanBePrivate") -open class SpigotTasks( - project: Project, - tasks: TaskContainer = project.tasks, - cache: Path = project.layout.cache, - extension: PaperweightCoreExtension = project.coreExt, -) : InitialTasks(project) { - - val cloneSpigotBuildData by tasks.registering { - url.set("https://hub.spigotmc.org/stash/scm/spigot/builddata.git") - ref.set(project.coreExt.spigot.buildDataRef) - } - - val unpackSpigotBuildData by tasks.registering { - buildDataZip.set(cloneSpigotBuildData.flatMap { it.outputZip }) - } - - val buildDataInfo: Provider = unpackSpigotBuildData - .flatMap { it.buildDataInfoFile } - .map { gson.fromJson(it.path) } - - val generateSpigotMappings by tasks.registering { - classMappings.set(unpackSpigotBuildData.flatMap { it.classMappings }) - - sourceMappings.set(generateMappings.flatMap { it.outputMappings }) - - outputMappings.set(cache.resolve(SPIGOT_MOJANG_MAPPINGS)) - notchToSpigotMappings.set(cache.resolve(OBF_SPIGOT_MAPPINGS)) - spigotMemberMappings.set(cache.resolve(SPIGOT_MEMBER_MAPPINGS)) - } - - val spigotRemapJar by tasks.registering { - inputJar.set(filterVanillaJar.flatMap { it.outputJar }) - classMappings.set(unpackSpigotBuildData.flatMap { it.classMappings }) - accessTransformers.set(unpackSpigotBuildData.flatMap { it.atFile }) - - memberMappings.set(generateSpigotMappings.flatMap { it.spigotMemberMappings }) - - mcVersion.set(extension.minecraftVersion) - - specialSourceJar.set(unpackSpigotBuildData.flatMap { it.specialSourceJar }) - specialSource2Jar.set(unpackSpigotBuildData.flatMap { it.specialSource2Jar }) - - classMapCommand.set(buildDataInfo.map { it.classMapCommand }) - memberMapCommand.set(buildDataInfo.map { it.memberMapCommand }) - finalMapCommand.set(buildDataInfo.map { it.finalMapCommand }) - } - - val cleanupMappings by tasks.registering { - sourceJar.set(spigotRemapJar.flatMap { it.outputJar }) - libraries.from(extractFromBundler.map { it.serverLibraryJars.asFileTree }) - inputMappings.set(generateSpigotMappings.flatMap { it.outputMappings }) - - outputMappings.set(cache.resolve(CLEANED_SPIGOT_MOJANG_MAPPINGS)) - } - - val patchMappings by tasks.registering { - inputMappings.set(cleanupMappings.flatMap { it.outputMappings }) - patch.set(extension.paper.mappingsPatch.fileExists()) - - fromNamespace.set(SPIGOT_NAMESPACE) - toNamespace.set(DEOBF_NAMESPACE) - - outputMappings.set(cache.resolve(PATCHED_SPIGOT_MOJANG_MAPPINGS)) - } -} diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/tasks/patchroulette/PatchRouletteApply.kt b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/tasks/patchroulette/PatchRouletteApply.kt index a86b069b7..ff42a81a3 100644 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/tasks/patchroulette/PatchRouletteApply.kt +++ b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/tasks/patchroulette/PatchRouletteApply.kt @@ -50,6 +50,9 @@ import org.gradle.api.tasks.options.Option * Paperweight will select `n` patches, prioritizing patches in the current package. * The only time less than `n` patches will be selected is if the entire patch roulette * instance has less than `n` patches available, in which case all of them will be selected. + * - `[,...]`: A comma separated list of patch paths. + * Paperweight will attempt to select exactly the provided patch paths. + * If any of the provided patches are not available, the task will fail. */ abstract class PatchRouletteApply : AbstractPatchRouletteTask() { @@ -72,6 +75,11 @@ abstract class PatchRouletteApply : AbstractPatchRouletteTask() { @get:Option(option = "reapplyPatches", description = "Whether to reapply current selected patched") abstract val reapplyPatches: Property + @get:Input + @get:Optional + @get:Option(option = "accept", description = "Automatically accept selected patches") + abstract val autoAccept: Property + override fun run() { config.path.createParentDirectories() var config = if (config.path.isRegularFile()) { @@ -126,14 +134,16 @@ abstract class PatchRouletteApply : AbstractPatchRouletteTask() { logger.lifecycle("===============================================") patches.forEach { logger.lifecycle(it.pathString) } - var response: String? = null - while (response != "y" && response != "n") { - response = System.`in`.bufferedReader().readLine() - } - if (response == "n") { - config = config.copy(skip = config.skip + patches) - this.config.path.writeText(gson.toJson(config)) - continue + if (!autoAccept.getOrElse(false)) { + var response: String? = null + while (response != "y" && response != "n") { + response = System.`in`.bufferedReader().readLine() + } + if (response == "n") { + config = config.copy(skip = config.skip + patches) + this.config.path.writeText(gson.toJson(config)) + continue + } } try { @@ -209,17 +219,42 @@ abstract class PatchRouletteApply : AbstractPatchRouletteTask() { } } + data class SpecificPatches(val patches: List) : PatchSelectionStrategy { + override fun select(config: Config, available: List): Pair> { + val availableSet = available.toSet() + val unavailable = patches.filterNot { availableSet.contains(it) } + if (unavailable.isNotEmpty()) { + throw PaperweightException( + "Failed to select specific patches. The following patches are unavailable: " + + unavailable.joinToString(", ") { it.invariantSeparatorsPathString } + ) + } + + return config to patches + } + } + fun select(config: Config, available: List): Pair> companion object { fun parse(input: String): PatchSelectionStrategy { try { + val normalizedInput = input.trim() return when { - input.endsWith("!") -> NumericInPackage(input.substring(0, input.length - 1).toInt(), true) - else -> NumericInPackage(input.toInt()) + normalizedInput.matches( + Regex("\\d+!") + ) -> NumericInPackage(normalizedInput.substring(0, normalizedInput.length - 1).toInt(), true) + normalizedInput.matches(Regex("\\d+")) -> NumericInPackage(normalizedInput.toInt()) + else -> { + val patches = normalizedInput.split(',').map { it.trim() }.filter { it.isNotEmpty() } + if (patches.isEmpty()) { + throw PaperweightException("Failed to parse patch selection strategy $normalizedInput") + } + SpecificPatches(patches.map { Path(it) }) + } } } catch (e: Exception) { - throw PaperweightException("Failed to parse patch selection strategy $input", e) + throw PaperweightException("Failed to parse patch selection strategy ${input.trim()}", e) } } } diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/tasks/patchroulette/PatchRouletteCancel.kt b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/tasks/patchroulette/PatchRouletteCancel.kt index b3a07b8e3..b87b6dab6 100644 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/tasks/patchroulette/PatchRouletteCancel.kt +++ b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/tasks/patchroulette/PatchRouletteCancel.kt @@ -42,20 +42,26 @@ abstract class PatchRouletteCancel : AbstractPatchRouletteTask() { @get:Option(option = "patch", description = "Cancel a patch by path instead of using the current patch") abstract val patch: Property + @get:Input + @get:Optional + @get:Option(option = "force", description = "Force canceling a patch even if it's not currently being worked on") + abstract val force: Property + override fun run() { val config = if (config.path.isRegularFile()) { gson.fromJson(config.path) } else { throw PaperweightException("No config exists") } - if (config.currentPatches.isEmpty()) { + val force = force.getOrElse(false) + if (!force && config.currentPatches.isEmpty()) { throw PaperweightException("No current patch in config") } val patchesToCancel = if (!patch.isPresent) { config.currentPatches } else { - if (!config.currentPatches.contains(Path(patch.get()))) { + if (!force && !config.currentPatches.contains(Path(patch.get()))) { throw PaperweightException("Cannot cancel patch ${patch.get()} as it isn't currently being worked on!") } diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/util/project-util.kt b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/util/project-util.kt index a3c668ac9..5954f4a71 100644 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/util/project-util.kt +++ b/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/util/project-util.kt @@ -23,81 +23,8 @@ package io.papermc.paperweight.core.util import io.papermc.paperweight.PaperweightException -import io.papermc.paperweight.core.extension.SpigotExtension -import io.papermc.paperweight.tasks.* -import io.papermc.paperweight.util.* import io.papermc.paperweight.util.constants.* -import org.gradle.api.Project import org.gradle.api.Task -import org.gradle.api.file.RegularFile -import org.gradle.api.provider.Provider -import org.gradle.api.tasks.bundling.AbstractArchiveTask -import org.gradle.kotlin.dsl.* - -fun Project.createBuildTasks( - spigot: SpigotExtension, - packagesToFix: Provider>, - relocatedReobfMappings: Provider -): ServerArtifacts { - val jar = tasks.named("jar", AbstractArchiveTask::class).flatMap { it.archiveFile } - - val fixJarForReobf by tasks.registering { - group = "build" - inputJar.set(jar) - packagesToProcess.set(packagesToFix) - } - - val includeMappings by tasks.registering { - group = "build" - inputJar.set(fixJarForReobf.flatMap { it.outputJar }) - mappings.set(relocatedReobfMappings) - mappingsDest.set("META-INF/mappings/reobf.tiny") - } - - // We only need to manually relocate references to CB class names in string constants, the actual relocation is handled by the mappings - val relocateConstants by tasks.registering { - group = "build" - inputJar.set(includeMappings.flatMap { it.outputJar }) - } - afterEvaluate { - relocateConstants { - relocate("org.bukkit.craftbukkit", "org.bukkit.craftbukkit.${spigot.packageVersion.get()}") { - // This is not actually needed as there are no string constant references to Main - // exclude("org.bukkit.craftbukkit.Main*") - } - } - } - - val reobfJar by tasks.registering { - group = "build" - description = "Re-obfuscate the built jar to obf mappings" - - reobfRequiresDebug() - - inputJar.set(relocateConstants.flatMap { it.outputJar }) - - mappingsFile.set(relocatedReobfMappings) - - fromNamespace.set(DEOBF_NAMESPACE) - toNamespace.set(SPIGOT_NAMESPACE) - - remapper.from(configurations.named(REMAPPER_CONFIG)) - remapperArgs.set(TinyRemapper.minecraftRemapArgs) - - outputJar.set(layout.buildDirectory.map { it.dir("libs").file("${project.name}-${project.version}-reobf.jar") }) - } - - return ServerArtifacts( - spigot.enabled.flatMap { - if (it) { - includeMappings.flatMap { t -> t.outputJar } - } else { - jar - } - }, - reobfJar.flatMap { it.outputJar } - ) -} fun Task.reobfRequiresDebug() { doFirst { @@ -110,8 +37,3 @@ fun Task.reobfRequiresDebug() { } } } - -data class ServerArtifacts( - val mappedJar: Provider, - val reobfJar: Provider, -) diff --git a/paperweight-core/src/test/kotlin/io/papermc/paperweight/core/tasks/patchroulette/PatchRouletteApplyTest.kt b/paperweight-core/src/test/kotlin/io/papermc/paperweight/core/tasks/patchroulette/PatchRouletteApplyTest.kt index dca09e16e..e9c318e5d 100644 --- a/paperweight-core/src/test/kotlin/io/papermc/paperweight/core/tasks/patchroulette/PatchRouletteApplyTest.kt +++ b/paperweight-core/src/test/kotlin/io/papermc/paperweight/core/tasks/patchroulette/PatchRouletteApplyTest.kt @@ -22,9 +22,11 @@ package io.papermc.paperweight.core.tasks.patchroulette +import io.papermc.paperweight.PaperweightException import kotlin.io.path.* import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertFailsWith import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.params.ParameterizedTest @@ -41,6 +43,8 @@ class PatchRouletteApplyTest { assertEquals(10, strategy.count) assertFalse(strategy.enforceCount) } + + is PatchRouletteApply.PatchSelectionStrategy.SpecificPatches -> error("Unexpected strategy type") } } @@ -52,6 +56,34 @@ class PatchRouletteApplyTest { assertEquals(20, strategy.count) assertTrue(strategy.enforceCount) } + + is PatchRouletteApply.PatchSelectionStrategy.SpecificPatches -> error("Unexpected strategy type") + } + } + + @Test + fun `test patch strategy parsing specific patches`() { + val strategy = PatchRouletteApply.PatchSelectionStrategy.parse("io/papermc/paper/block/Block.java, io/papermc/paper/entity/Entity.java") + when (strategy) { + is PatchRouletteApply.PatchSelectionStrategy.SpecificPatches -> { + assertEquals( + listOf(Path("io/papermc/paper/block/Block.java"), Path("io/papermc/paper/entity/Entity.java")), + strategy.patches + ) + } + + is PatchRouletteApply.PatchSelectionStrategy.NumericInPackage -> error("Unexpected strategy type") + } + } + + @Test + fun `test specific patch selection fails when patch unavailable`() { + val strategy = PatchRouletteApply.PatchSelectionStrategy.SpecificPatches( + listOf(Path("io/papermc/paper/block/Block.java"), Path("io/papermc/paper/entity/Missing.java")) + ) + + assertFailsWith { + strategy.select(PatchRouletteApply.Config(listOf(), null, listOf()), mockAvailablePatches().map { Path(it) }) } } @@ -137,6 +169,24 @@ class PatchRouletteApplyTest { "io/papermc/paper/entity/Entity3.java" ) ) + ), + Arguments.of( + PatchRouletteApply.PatchSelectionStrategy.SpecificPatches( + listOf( + Path("io/papermc/paper/block/BlockState.java"), + Path("io/papermc/paper/entity/Entity.java") + ) + ), + listOf( + "io/papermc/paper/block/BlockState.java", + "io/papermc/paper/entity/Entity.java" + ), + listOf( + listOf( + "io/papermc/paper/block/BlockState.java", + "io/papermc/paper/entity/Entity.java" + ) + ) ) ) diff --git a/paperweight-core/src/test/resources/fake_mache/mache.json b/paperweight-core/src/test/resources/fake_mache/mache.json index 5bf2d2a6d..1572ea46c 100644 --- a/paperweight-core/src/test/resources/fake_mache/mache.json +++ b/paperweight-core/src/test/resources/fake_mache/mache.json @@ -6,70 +6,26 @@ { "group": "io.papermc.codebook", "name": "codebook-cli", - "version": "1.0.10", + "version": "2.0.0-SNAPSHOT", "classifier": "all" } ], - "paramMappings": [ - { - "group": "org.parchmentmc.data", - "name": "parchment-1.21", - "version": "2024.07.28", - "extension": "zip" - } - ], "constants": [ ], - "remapper": [ - { - "group": "net.neoforged", - "name": "AutoRenamingTool", - "version": "1.0.14", - "classifier": "all" - } - ], "decompiler": [ { "group": "org.vineflower", "name": "vineflower", - "version": "1.11.0-20241204.173358-53" + "version": "1.11.2" } ] }, "repositories": [ - { - "url": "https://maven.fabricmc.net/", - "name": "FabricMC", - "groups": [ - "net.fabricmc" - ] - }, - { - "url": "https://maven.neoforged.net/releases/", - "name": "NeoForged", - "groups": [ - "net.neoforged", - "net.minecraftforge" - ] - }, { "url": "https://repo.papermc.io/repository/maven-public/", "name": "PaperMC", "groups": [ - "io.papermc" - ] - }, - { - "url": "https://maven.parchmentmc.org/", - "name": "ParchmentMC", - "groups": [ - "org.parchmentmc" - ] - }, - { - "url": "https://s01.oss.sonatype.org/content/repositories/snapshots/", - "name": "sonatype snapshots", - "groups": [ + "io.papermc", "org.vineflower" ] } @@ -95,12 +51,10 @@ ], "remapperArgs": [ "--temp-dir={tempDir}", - "--remapper-file={remapperFile}", - "--mappings-file={mappingsFile}", - "--params-file={paramsFile}", "--output={output}", "--input={input}", - "--input-classpath={inputClasspath}" + "--input-classpath={inputClasspath}", + "--hypo-parallelism=1" ], "additionalCompileDependencies": { "compileOnly": [ @@ -108,6 +62,16 @@ "group": "org.jetbrains", "name": "annotations", "version": "24.0.1" + }, + { + "group": "com.google.code.findbugs", + "name": "jsr305", + "version": "3.0.2" + }, + { + "group": "org.checkerframework", + "name": "checker-qual", + "version": "3.49.0" } ] } diff --git a/paperweight-core/src/test/resources/functional_test/test-server/build.gradle b/paperweight-core/src/test/resources/functional_test/test-server/build.gradle index 1e7185c18..c0f204edc 100644 --- a/paperweight-core/src/test/resources/functional_test/test-server/build.gradle +++ b/paperweight-core/src/test/resources/functional_test/test-server/build.gradle @@ -23,7 +23,7 @@ dependencies { // this could be resolved by creating a fake maven repo that holds proper module metadata implementation 'com.github.oshi:oshi-core:6.6.5' } else { - mache 'io.papermc:mache:1.21.4+build.4' + mache 'io.papermc:mache:26.1-snapshot-11+build.2' } } @@ -48,6 +48,6 @@ paperweight { resourcePatchDir.set(file('patches/resources')) featurePatchDir.set(file('patches/features')) } - minecraftVersion = '1.21.4' + minecraftVersion = '26.1-snapshot-11' } } diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/FilterJar.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/FilterJar.kt deleted file mode 100644 index 479b232d1..000000000 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/FilterJar.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* - * paperweight is a Gradle plugin for the PaperMC project. - * - * Copyright (c) 2023 Kyle Wood (DenWav) - * Contributors - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 only, no later versions. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package io.papermc.paperweight.tasks - -import io.papermc.paperweight.util.* -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.provider.ListProperty -import org.gradle.api.tasks.CacheableTask -import org.gradle.api.tasks.Classpath -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.OutputFile -import org.gradle.api.tasks.TaskAction - -@CacheableTask -abstract class FilterJar : BaseTask() { - - @get:Classpath - abstract val inputJar: RegularFileProperty - - @get:Input - abstract val includes: ListProperty - - @get:OutputFile - abstract val outputJar: RegularFileProperty - - override fun init() { - outputJar.convention(defaultOutput()) - } - - @TaskAction - open fun run() { - filterJar( - inputJar.path, - outputJar.path, - includes.get() - ) - } -} diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/FixJarForReobf.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/FixJarForReobf.kt deleted file mode 100644 index 51c688103..000000000 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/FixJarForReobf.kt +++ /dev/null @@ -1,227 +0,0 @@ -/* - * paperweight is a Gradle plugin for the PaperMC project. - * - * Copyright (c) 2023 Kyle Wood (DenWav) - * Contributors - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 only, no later versions. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package io.papermc.paperweight.tasks - -import io.papermc.paperweight.util.* -import java.nio.file.Path -import javax.inject.Inject -import kotlin.io.path.* -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.provider.ListProperty -import org.gradle.api.tasks.Classpath -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.Optional -import org.gradle.api.tasks.OutputFile -import org.gradle.api.tasks.TaskAction -import org.gradle.kotlin.dsl.* -import org.gradle.workers.WorkAction -import org.gradle.workers.WorkParameters -import org.gradle.workers.WorkerExecutor -import org.objectweb.asm.Opcodes -import org.objectweb.asm.tree.ClassNode -import org.objectweb.asm.tree.FieldInsnNode -import org.objectweb.asm.tree.MethodNode - -abstract class FixJarForReobf : JavaLauncherTask() { - - @get:Classpath - abstract val inputJar: RegularFileProperty - - @get:Optional - @get:Input - abstract val packagesToProcess: ListProperty - - @get:OutputFile - abstract val outputJar: RegularFileProperty - - @get:Internal - abstract val jvmargs: ListProperty - - @get:Inject - abstract val workerExecutor: WorkerExecutor - - override fun init() { - super.init() - - outputJar.convention(defaultOutput()) - jvmargs.convention(listOf("-Xmx2G")) - } - - @TaskAction - fun run() { - val pack = packagesToProcess.orNull - if (pack == null) { - inputJar.path.copyTo(outputJar.path) - return - } - - val queue = workerExecutor.processIsolation { - forkOptions.jvmArgs(jvmargs.get()) - forkOptions.executable(launcher.get().executablePath.path.absolutePathString()) - } - - queue.submit(FixJarForReobfWorker::class) { - inputJar.set(this@FixJarForReobf.inputJar.path) - packagesToProcess.set(pack) - outputJar.set(this@FixJarForReobf.outputJar.path) - } - } - - interface FixJarForReobfParams : WorkParameters { - val inputJar: RegularFileProperty - val packagesToProcess: ListProperty - val outputJar: RegularFileProperty - } - - abstract class FixJarForReobfWorker : WorkAction { - - override fun execute() { - val packages = normalize(parameters.packagesToProcess.get()) - - val output = parameters.outputJar.path - output.parent.createDirectories() - output.deleteForcefully() - - output.writeZip().use { out -> - parameters.inputJar.path.openZip().use { jarFile -> - JarProcessing.processJar(jarFile, out, FixForReobfProcessor(packages)) - } - } - } - - class FixForReobfProcessor(private val packages: List) : JarProcessing.ClassProcessor.NodeBased { - override fun shouldProcess(file: Path): Boolean = - packages.any { file.toString().startsWith(it) } - - override fun processClass(node: ClassNode, classNodeCache: ClassNodeCache) { - FieldAccessNormalizer(node, classNodeCache).visitNode() - } - } - - private fun normalize(input: List): List { - return input.map { name -> - '/' + name.removePrefix("/").replace('.', '/') - } - } - } -} - -/* - * This resolves issues caused by reobf prior to the reobf process. After reobf this is impossible to do - the field access become ambiguous (which is - * what this fixes). - * - * What exactly this is fixing requires some knowledge around how the JVM handles field accesses in the first place - Mumfrey described this process - * in detail with some great diagrams several years ago, you can read that here: https://github.com/MinecraftForge/MinecraftForge/pull/3055 - * - * The goal of this class is to check all field access instructions (not field declarations) and follow the JVM's rules for field binding in order - * to determine the _intended_ owning class of a field access. Prior to reobf all of this works exactly as expected when looking at Java source code, - * but after reobf there are many cases that look like this: - * - * field `a` declared in class `Foo` - * field `a` declared in class `Bar` which extends `Foo` - * - * In the deobfuscated code these fields would have different names, so they won't overlap and the JVM will output field access instructions described - * in the link above. Reobf generally only changes the field's name and type (and the name of the owner class), but it doesn't actually fix the issue - * where field accesses which used to be unambiguous are now ambiguous. - * - * So with that in mind, this class will look at field access instructions and match the actual field the instruction is trying to access (even if - * it's not directly declared in the owner class) and change the owner accordingly. This will keep field accesses unambiguous even after reobf with - * conflicting field names. - */ -class FieldAccessNormalizer(private val node: ClassNode, private val classNodeCache: ClassNodeCache) : AsmUtil { - - fun visitNode() { - for (method in node.methods) { - visitMethod(method) - } - } - - private fun visitMethod(method: MethodNode) { - for (instruction in method.instructions) { - val fieldInst = instruction as? FieldInsnNode ?: continue - visitFieldInst(fieldInst) - } - } - - private fun visitFieldInst(instruction: FieldInsnNode) { - val ownerNode = findTargetFieldDeclaration(instruction) ?: return - instruction.owner = ownerNode.name - } - - private fun findTargetFieldDeclaration(instruction: FieldInsnNode): ClassNode? { - val fieldName = instruction.name - - var className: String? = instruction.owner - while (className != null) { - val currentNode = classNodeCache.findClass(className) ?: return null - - val fieldNode = currentNode.fields.firstOrNull { it.name == fieldName } - if (fieldNode != null) { - /* - * We need to determine if this field node can actually be accessed by the caller (the original `node`). - * For example, consider the following class hierarchy: - * - * class Foo - * public field text - * class Bar extends Foo - * private field text - * class Cat extends Bar - * - * If `Cat` contains a method which accesses `this.text` then by Java's field access rules the field access would bind to `Foo.text` - * rather than `Bar.text`, even though `Bar.text` shadows `Foo.text`. This is of course because `Cat` is not able to access `Bar.text` - * since it's a private field. Private fields are of course the easier case to handle - we also have to check protected fields if the - * original `node` does not extend the field's declaring class, and package private if the classes aren't in the same package. - */ - - if (Opcodes.ACC_PRIVATE in fieldNode.access) { - // This is only legal if the field node owner and the original node match - if (currentNode.name == node.name) { - return currentNode - } - } else if (Opcodes.ACC_PROTECTED in fieldNode.access) { - var walkingNode: ClassNode? = node - while (walkingNode != null) { - if (walkingNode.name == currentNode.name) { - return currentNode - } - walkingNode = classNodeCache.findClass(walkingNode.superName) - } - } else if (Opcodes.ACC_PUBLIC in fieldNode.access) { - return currentNode - } else { - // package private field - val currentPackage = currentNode.name.substringBeforeLast('/') - val originalPackage = node.name.substringBeforeLast('/') - if (currentPackage == originalPackage) { - return currentNode - } - } - } - - className = currentNode.superName - } - - return null - } -} diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/GenerateDevBundle.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/GenerateDevBundle.kt index 897a993ca..d32e52837 100644 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/GenerateDevBundle.kt +++ b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/GenerateDevBundle.kt @@ -43,7 +43,6 @@ import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputDirectory import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.InputFiles -import org.gradle.api.tasks.Optional import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.TaskAction @@ -70,10 +69,6 @@ abstract class GenerateDevBundle : BaseTask() { @get:Input abstract val macheDep: Property - @get:InputFile - @get:Optional - abstract val reobfMappingsFile: RegularFileProperty - @get:OutputFile abstract val devBundleFile: RegularFileProperty @@ -103,9 +98,6 @@ abstract class GenerateDevBundle : BaseTask() { val dataZip = zip.getPath(dataDir) dataZip.createDirectories() - if (reobfMappingsFile.isPresent) { - reobfMappingsFile.path.copyTo(dataZip.resolve(reobfMappingsFileName)) - } mojangMappedPaperclipFile.path.copyTo(dataZip.resolve(mojangMappedPaperclipFileName)) val patchesZip = zip.getPath(patchesDir) @@ -191,7 +183,6 @@ abstract class GenerateDevBundle : BaseTask() { minecraftVersion = minecraftVersion.get(), mache = createMacheDep(), patchDir = patchTargetDir, - reobfMappingsFile = if (reobfMappingsFile.isPresent) "$dataTargetDir/$reobfMappingsFileName" else null, mojangMappedPaperclipFile = "$dataTargetDir/$mojangMappedPaperclipFileName", libraryRepositories = libraryRepositories.get(), pluginRemapArgs = TinyRemapper.pluginRemapArgs, @@ -205,17 +196,15 @@ abstract class GenerateDevBundle : BaseTask() { val minecraftVersion: String, val mache: MavenDep, val patchDir: String, - val reobfMappingsFile: String?, val mojangMappedPaperclipFile: String, val libraryRepositories: List, val pluginRemapArgs: List, ) companion object { - const val reobfMappingsFileName = "$DEOBF_NAMESPACE-$SPIGOT_NAMESPACE-reobf.tiny" const val mojangMappedPaperclipFileName = "paperclip-$DEOBF_NAMESPACE.jar" // Should be bumped when the dev bundle config/contents changes in a way which will require users to update paperweight - const val currentDataVersion = 7 + const val currentDataVersion = 8 } } diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/GenerateMappings.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/GenerateMappings.kt index 6e4b46cd4..6075b731e 100644 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/GenerateMappings.kt +++ b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/GenerateMappings.kt @@ -36,7 +36,6 @@ import dev.denwav.hypo.model.ClassProviderRoot import io.papermc.paperweight.util.* import io.papermc.paperweight.util.constants.* import java.nio.file.Path -import javax.inject.Inject import kotlin.io.path.* import org.cadixdev.lorenz.MappingSet import org.cadixdev.lorenz.merge.FieldMergeStrategy @@ -53,9 +52,7 @@ import org.cadixdev.lorenz.model.MethodParameterMapping import org.cadixdev.lorenz.model.TopLevelClassMapping import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.RegularFileProperty -import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Property -import org.gradle.api.tasks.* import org.gradle.jvm.toolchain.JavaLauncher import org.gradle.kotlin.dsl.* import org.gradle.workers.WorkAction @@ -79,7 +76,7 @@ fun generateMappings( forkOptions.executable(launcher.executablePath.path.absolutePathString()) } - queue.submit(GenerateMappings.GenerateMappingsAction::class) { + queue.submit(GenerateMappingsAction::class) { vanillaJar.set(vanillaJarPath) libraries.from(libraryPaths) vanillaMappings.set(vanillaMappingsPath) @@ -91,106 +88,57 @@ fun generateMappings( return queue } -@CacheableTask -abstract class GenerateMappings : JavaLauncherTask() { - - @get:Classpath - abstract val vanillaJar: RegularFileProperty - - @get:Classpath - abstract val libraries: ConfigurableFileCollection - - @get:InputFile - @get:PathSensitive(PathSensitivity.NONE) - abstract val vanillaMappings: RegularFileProperty - - @get:InputFile - @get:Optional - @get:PathSensitive(PathSensitivity.NONE) - abstract val paramMappings: RegularFileProperty - - @get:OutputFile - abstract val outputMappings: RegularFileProperty - - @get:Internal - abstract val jvmargs: ListProperty - - @get:Inject - abstract val workerExecutor: WorkerExecutor - - override fun init() { - super.init() - - jvmargs.convention(listOf("-Xmx1G")) - } - - @TaskAction - fun run() { - generateMappings( - vanillaJar.path, - libraries.files.map { it.toPath() }, - vanillaMappings.path, - paramMappings.pathOrNull, - outputMappings.path, - DEOBF_NAMESPACE, - workerExecutor, - launcher.get(), - jvmargs.get() - ) - } - - interface GenerateMappingsParams : WorkParameters { - val vanillaJar: RegularFileProperty - val libraries: ConfigurableFileCollection - val vanillaMappings: RegularFileProperty - val paramMappings: RegularFileProperty - val outputMappings: RegularFileProperty - val deobfNamespace: Property - } +interface GenerateMappingsParams : WorkParameters { + val vanillaJar: RegularFileProperty + val libraries: ConfigurableFileCollection + val vanillaMappings: RegularFileProperty + val paramMappings: RegularFileProperty + val outputMappings: RegularFileProperty + val deobfNamespace: Property +} - abstract class GenerateMappingsAction : WorkAction { +abstract class GenerateMappingsAction : WorkAction { - override fun execute() { - val vanillaMappings = MappingFormats.PROGUARD.createReader(parameters.vanillaMappings.path).use { it.read() }.reverse() + override fun execute() { + val vanillaMappings = MappingFormats.PROGUARD.createReader(parameters.vanillaMappings.path).use { it.read() }.reverse() - val paramMappings = parameters.paramMappings.orNull?.let { mappingsFile -> - mappingsFile.path.openZip().use { fs -> - val path = fs.getPath("mappings", "mappings.tiny") - MappingFormats.TINY.read(path, "official", "named") - } + val paramMappings = parameters.paramMappings.orNull?.let { mappingsFile -> + mappingsFile.path.openZip().use { fs -> + val path = fs.getPath("mappings", "mappings.tiny") + MappingFormats.TINY.read(path, "official", "named") } + } - val merged = paramMappings?.let { - MappingSetMerger.create( - vanillaMappings, - it, - MergeConfig.builder() - .withFieldMergeStrategy(FieldMergeStrategy.STRICT) - .withMergeHandler(ParamsMergeHandler()) - .build() - ).merge() - } ?: vanillaMappings - - val filledMerged = HypoContext.builder() - .withProvider(AsmClassDataProvider.of(ClassProviderRoot.fromJar(parameters.vanillaJar.path))) - .withContextProvider(AsmClassDataProvider.of(parameters.libraries.toJarClassProviderRoots())) - .withContextProvider(AsmClassDataProvider.of(ClassProviderRoot.ofJdk())) - .build().use { hypoContext -> - HydrationManager.createDefault() - .register(BridgeMethodHydrator.create()) - .register(SuperConstructorHydrator.create()) - .hydrate(hypoContext) - - ChangeChain.create() - .addLink(RemoveUnusedMappings.create()) - .addLink(PropagateMappingsUp.create()) - .addLink(CopyMappingsDown.create()) - .applyChain(merged, MappingsCompletionManager.create(hypoContext)) - } + val merged = paramMappings?.let { + MappingSetMerger.create( + vanillaMappings, + it, + MergeConfig.builder() + .withFieldMergeStrategy(FieldMergeStrategy.STRICT) + .withMergeHandler(ParamsMergeHandler()) + .build() + ).merge() + } ?: vanillaMappings + + val filledMerged = HypoContext.builder() + .withProvider(AsmClassDataProvider.of(ClassProviderRoot.fromJar(parameters.vanillaJar.path))) + .withContextProvider(AsmClassDataProvider.of(parameters.libraries.toJarClassProviderRoots())) + .withContextProvider(AsmClassDataProvider.of(ClassProviderRoot.ofJdk())) + .build().use { hypoContext -> + HydrationManager.createDefault() + .register(BridgeMethodHydrator.create()) + .register(SuperConstructorHydrator.create()) + .hydrate(hypoContext) + + ChangeChain.create() + .addLink(RemoveUnusedMappings.create()) + .addLink(PropagateMappingsUp.create()) + .addLink(CopyMappingsDown.create()) + .applyChain(merged, MappingsCompletionManager.create(hypoContext)) + } - ensureParentExists(parameters.outputMappings) - MappingFormats.TINY.write(filledMerged, parameters.outputMappings.path, OBF_NAMESPACE, parameters.deobfNamespace.get()) - } + ensureParentExists(parameters.outputMappings) + MappingFormats.TINY.write(filledMerged, parameters.outputMappings.path, OBF_NAMESPACE, parameters.deobfNamespace.get()) } } diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/GenerateRelocatedReobfMappings.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/GenerateRelocatedReobfMappings.kt deleted file mode 100644 index 9d7a0afb6..000000000 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/GenerateRelocatedReobfMappings.kt +++ /dev/null @@ -1,155 +0,0 @@ -/* - * paperweight is a Gradle plugin for the PaperMC project. - * - * Copyright (c) 2023 Kyle Wood (DenWav) - * Contributors - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 only, no later versions. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package io.papermc.paperweight.tasks - -import dev.denwav.hypo.asm.AsmClassDataProvider -import dev.denwav.hypo.core.HypoConfig -import dev.denwav.hypo.core.HypoContext -import dev.denwav.hypo.hydrate.HydrationManager -import dev.denwav.hypo.mappings.ChangeChain -import dev.denwav.hypo.mappings.ChangeRegistry -import dev.denwav.hypo.mappings.MappingsCompletionManager -import dev.denwav.hypo.mappings.contributors.ChangeContributor -import dev.denwav.hypo.model.ClassProviderRoot -import dev.denwav.hypo.model.data.ClassData -import io.papermc.paperweight.util.* -import io.papermc.paperweight.util.constants.* -import javax.inject.Inject -import kotlin.io.path.* -import org.cadixdev.lorenz.model.ClassMapping -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.provider.ListProperty -import org.gradle.api.provider.Property -import org.gradle.api.tasks.* -import org.gradle.kotlin.dsl.* -import org.gradle.workers.WorkAction -import org.gradle.workers.WorkParameters -import org.gradle.workers.WorkerExecutor - -abstract class GenerateRelocatedReobfMappings : JavaLauncherTask() { - - @get:InputFile - @get:PathSensitive(PathSensitivity.NONE) - abstract val inputMappings: RegularFileProperty - - @get:Classpath - abstract val inputJar: RegularFileProperty - - @get:OutputFile - abstract val outputMappings: RegularFileProperty - - @get:Internal - abstract val jvmArgs: ListProperty - - @get:Inject - abstract val workerExecutor: WorkerExecutor - - @get:Input - abstract val craftBukkitPackageVersion: Property - - override fun init() { - super.init() - - jvmArgs.convention(listOf("-Xmx2G")) - } - - @TaskAction - fun run() { - val queue = workerExecutor.processIsolation { - forkOptions.jvmArgs(jvmArgs.get()) - forkOptions.executable(launcher.get().executablePath.path.absolutePathString()) - } - - queue.submit(Action::class) { - inputMappings.set(this@GenerateRelocatedReobfMappings.inputMappings) - inputJar.set(this@GenerateRelocatedReobfMappings.inputJar) - craftBukkitPackageVersion.set(this@GenerateRelocatedReobfMappings.craftBukkitPackageVersion) - - outputMappings.set(this@GenerateRelocatedReobfMappings.outputMappings) - } - } - - abstract class Action : WorkAction { - interface Parameters : WorkParameters { - val inputMappings: RegularFileProperty - val inputJar: RegularFileProperty - val craftBukkitPackageVersion: Property - - val outputMappings: RegularFileProperty - } - - override fun execute() { - val mappingsIn = MappingFormats.TINY.read( - parameters.inputMappings.path, - DEOBF_NAMESPACE, - SPIGOT_NAMESPACE - ) - val mappingsOut = HypoContext.builder() - .withConfig(HypoConfig.builder().setRequireFullClasspath(false).withParallelism(1).build()) - .withProvider(AsmClassDataProvider.of(ClassProviderRoot.fromJar(parameters.inputJar.path))) - .withContextProvider(AsmClassDataProvider.of(ClassProviderRoot.ofJdk())) - .build().use { hypoContext -> - HydrationManager.createDefault().hydrate(hypoContext) - ChangeChain.create() - .addLink(CraftBukkitRelocation(parameters.craftBukkitPackageVersion.get())) - .applyChain(mappingsIn, MappingsCompletionManager.create(hypoContext)) - } - MappingFormats.TINY.write( - mappingsOut, - parameters.outputMappings.path, - DEOBF_NAMESPACE, - SPIGOT_NAMESPACE - ) - } - } - - class CraftBukkitRelocation(packageVersion: String) : ChangeContributor { - companion object { - const val PREFIX = "org/bukkit/craftbukkit/" - const val MAIN = "${PREFIX}Main" - } - - private val relocateTo: String = "$PREFIX$packageVersion" - - override fun name(): String = "CraftBukkitRelocation" - - override fun contribute( - currentClass: ClassData?, - classMapping: ClassMapping<*, *>?, - context: HypoContext, - registry: ChangeRegistry - ) { - if (currentClass == null || classMapping != null) { - return - } - if (currentClass.name().startsWith(PREFIX) && !currentClass.name().startsWith(MAIN)) { - registry.submitChange( - GenerateReobfMappings.AddClassMappingChange( - currentClass.name(), - "$relocateTo/${currentClass.name().substring(PREFIX.length)}" - ) - ) - } - } - } -} diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/GenerateReobfMappings.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/GenerateReobfMappings.kt deleted file mode 100644 index 5ceef3922..000000000 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/GenerateReobfMappings.kt +++ /dev/null @@ -1,315 +0,0 @@ -/* - * paperweight is a Gradle plugin for the PaperMC project. - * - * Copyright (c) 2023 Kyle Wood (DenWav) - * Contributors - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 only, no later versions. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package io.papermc.paperweight.tasks - -import dev.denwav.hypo.asm.AsmClassDataProvider -import dev.denwav.hypo.asm.hydrate.BridgeMethodHydrator -import dev.denwav.hypo.asm.hydrate.SuperConstructorHydrator -import dev.denwav.hypo.core.HypoConfig -import dev.denwav.hypo.core.HypoContext -import dev.denwav.hypo.hydrate.HydrationManager -import dev.denwav.hypo.mappings.ChangeChain -import dev.denwav.hypo.mappings.ChangeRegistry -import dev.denwav.hypo.mappings.ClassMappingsChange -import dev.denwav.hypo.mappings.MappingsCompletionManager -import dev.denwav.hypo.mappings.changes.MemberReference -import dev.denwav.hypo.mappings.changes.RemoveMappingChange -import dev.denwav.hypo.mappings.contributors.ChangeContributor -import dev.denwav.hypo.mappings.contributors.RemoveUnusedMappings -import dev.denwav.hypo.model.ClassProviderRoot -import dev.denwav.hypo.model.data.ClassData -import io.papermc.paperweight.util.* -import io.papermc.paperweight.util.constants.* -import javax.inject.Inject -import kotlin.io.path.* -import org.cadixdev.lorenz.MappingSet -import org.cadixdev.lorenz.model.ClassMapping -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.provider.ListProperty -import org.gradle.api.tasks.* -import org.gradle.kotlin.dsl.* -import org.gradle.workers.WorkAction -import org.gradle.workers.WorkParameters -import org.gradle.workers.WorkerExecutor - -abstract class GenerateReobfMappings : JavaLauncherTask() { - - @get:InputFile - @get:PathSensitive(PathSensitivity.NONE) - abstract val inputMappings: RegularFileProperty - - @get:InputFile - @get:PathSensitive(PathSensitivity.NONE) - abstract val notchToSpigotMappings: RegularFileProperty - - @get:InputFile - @get:PathSensitive(PathSensitivity.NONE) - abstract val sourceMappings: RegularFileProperty - - @get:Classpath - abstract val inputJar: RegularFileProperty - - @get:OutputFile - abstract val reobfMappings: RegularFileProperty - - @get:Internal - abstract val jvmArgs: ListProperty - - @get:Inject - abstract val workerExecutor: WorkerExecutor - - @get:InputFile - @get:Optional - @get:PathSensitive(PathSensitivity.NONE) - abstract val spigotRecompiledClasses: RegularFileProperty - - override fun init() { - super.init() - - jvmArgs.convention(listOf("-Xmx2G")) - } - - @TaskAction - fun run() { - val queue = workerExecutor.processIsolation { - forkOptions.jvmArgs(jvmArgs.get()) - forkOptions.executable(launcher.get().executablePath.path.absolutePathString()) - } - - queue.submit(GenerateReobfMappingsAction::class) { - inputMappings.set(this@GenerateReobfMappings.inputMappings) - notchToSpigotMappings.set(this@GenerateReobfMappings.notchToSpigotMappings) - sourceMappings.set(this@GenerateReobfMappings.sourceMappings) - inputJar.set(this@GenerateReobfMappings.inputJar) - spigotRecompiles.set(spigotRecompiledClasses.pathOrNull) - - reobfMappings.set(this@GenerateReobfMappings.reobfMappings) - } - } - - // https://github.com/PaperMC/paperweight/issues/18 - class PropagateOuterClassMappings(private val mappings: MappingSet) : ChangeContributor { - - override fun contribute(currentClass: ClassData?, classMapping: ClassMapping<*, *>?, context: HypoContext, registry: ChangeRegistry) { - if (currentClass == null || classMapping != null) { - return - } - - val name = currentClass.name().substringAfterLast("$") - - val outer = currentClass.outerClass() ?: return - val outerMappings = mappings.getClassMapping(outer.name()).orNull ?: return - if (outerMappings.innerClassMappings.any { it.deobfuscatedName == name }) { - return - } - - registry.submitChange(AddClassMappingChange(currentClass.name(), name)) - } - - override fun name(): String = "PropagateOuterClassMappings" - } - - class AddClassMappingChange(private val target: String, private val deobfName: String) : ClassMappingsChange { - override fun targetClass(): String = target - - override fun applyChange(input: MappingSet) { - input.getOrCreateClassMapping(target).deobfuscatedName = deobfName - } - } - - class RemoveRecompiledSyntheticMemberMappings(private val recompiledClasses: Set) : ChangeContributor { - override fun contribute( - currentClass: ClassData?, - classMapping: ClassMapping<*, *>?, - context: HypoContext, - registry: ChangeRegistry - ) { - if (currentClass == null || classMapping == null) { - return - } - if (currentClass.rootClass().name() !in recompiledClasses) { - return - } - - for (method in currentClass.methods()) { - if (method.isSynthetic) { - registry.submitChange(RemoveMappingChange.of(MemberReference.of(method))) - } - } - - for (field in currentClass.fields()) { - if (field.isSynthetic) { - registry.submitChange(RemoveMappingChange.of(MemberReference.of(field))) - } - } - } - - private fun ClassData.rootClass(): ClassData = - allOuterClasses().getOrNull(0) ?: this - - private fun ClassData.allOuterClasses(list: MutableList = ArrayList()): List { - val outer = outerClass() ?: return list.reversed() - list.add(outer) - return outer.allOuterClasses(list) - } - - override fun name(): String = "RemoveRecompiledSyntheticMemberMappings" - } - - interface GenerateReobfMappingsParams : WorkParameters { - val inputMappings: RegularFileProperty - val notchToSpigotMappings: RegularFileProperty - val sourceMappings: RegularFileProperty - val inputJar: RegularFileProperty - val spigotRecompiles: RegularFileProperty - - val reobfMappings: RegularFileProperty - } - - abstract class GenerateReobfMappingsAction : WorkAction { - - override fun execute() { - val spigotToMojang = MappingFormats.TINY.read( - parameters.inputMappings.path, - SPIGOT_NAMESPACE, - DEOBF_NAMESPACE - ) - val obfToSpigot = MappingFormats.TINY.read( - parameters.notchToSpigotMappings.path, - OBF_NAMESPACE, - SPIGOT_NAMESPACE - ) - val obfToMojang = MappingFormats.TINY.read( - parameters.sourceMappings.path, - OBF_NAMESPACE, - DEOBF_NAMESPACE - ) - - val outputMappings = mergeSpigotWithMojangMemberMappings(obfToSpigot, obfToMojang, spigotToMojang) - - val spigotRecompiles = parameters.spigotRecompiles.pathOrNull?.readLines()?.toSet() ?: emptySet() - - val cleanedOutputMappings = HypoContext.builder() - .withConfig(HypoConfig.builder().setRequireFullClasspath(false).withParallelism(1).build()) - .withProvider(AsmClassDataProvider.of(ClassProviderRoot.fromJar(parameters.inputJar.path))) - .withContextProvider(AsmClassDataProvider.of(ClassProviderRoot.ofJdk())) - .build().use { hypoContext -> - HydrationManager.createDefault() - .register(BridgeMethodHydrator.create()) - .register(SuperConstructorHydrator.create()) - .hydrate(hypoContext) - - ChangeChain.create() - .addLink(RemoveUnusedMappings.create()) - .addLink(RemoveRecompiledSyntheticMemberMappings(spigotRecompiles)) - .addLink(PropagateOuterClassMappings(outputMappings)) - .applyChain(outputMappings, MappingsCompletionManager.create(hypoContext)) - } - - MappingFormats.TINY.write( - cleanedOutputMappings, - parameters.reobfMappings.path, - DEOBF_NAMESPACE, - SPIGOT_NAMESPACE - ) - } - - private fun mergeSpigotWithMojangMemberMappings(obfToSpigot: MappingSet, obfToMojang: MappingSet, spigotToMojang: MappingSet): MappingSet { - val output = MappingSet.create() - - for (mojangClassMapping in obfToMojang.topLevelClassMappings) { - val spigotClassMapping = obfToSpigot.getTopLevelClassMapping(mojangClassMapping.obfuscatedName).orNull - val paperMojangClassMapping = spigotClassMapping?.deobfuscatedName?.let { spigotToMojang.getTopLevelClassMapping(it) }?.orNull - - val fromClassName = mojangClassMapping.deobfuscatedName - val toClassName = if (spigotClassMapping != null && spigotClassMapping.obfuscatedName != spigotClassMapping.deobfuscatedName) { - spigotClassMapping.deobfuscatedName - } else { - mojangClassMapping.deobfuscatedName - } - - // package-info and nullability annotations don't need to be reobfed - if (fromClassName.endsWith("package-info") || fromClassName.endsWith("NonnullByDefault")) { - continue - } - - val newClassMapping = output.createTopLevelClassMapping(fromClassName, toClassName) - mergeSpigotWithMojangMemberMappings(spigotClassMapping, mojangClassMapping, paperMojangClassMapping, newClassMapping) - } - - return output - } - - private fun mergeSpigotWithMojangMemberMappings( - spigotClassMapping: ClassMapping<*, *>?, - mojangClassMapping: ClassMapping<*, *>, - paperMojangClassMapping: ClassMapping<*, *>?, - targetMappings: ClassMapping<*, *> - ) { - for (mojangInnerClassMapping in mojangClassMapping.innerClassMappings) { - val spigotInnerClassMapping = spigotClassMapping?.getInnerClassMapping(mojangInnerClassMapping.obfuscatedName)?.orNull - val paperMojangInnerClassMapping = spigotInnerClassMapping?.deobfuscatedName - ?.let { paperMojangClassMapping?.getInnerClassMapping(it) }?.orNull - - val fromInnerClassName = mojangInnerClassMapping.deobfuscatedName - val toInnerClassName = spigotInnerClassMapping?.deobfuscatedName ?: mojangInnerClassMapping.deobfuscatedName - - val newInnerClassMapping = targetMappings.createInnerClassMapping(fromInnerClassName, toInnerClassName) - mergeSpigotWithMojangMemberMappings( - spigotInnerClassMapping, - mojangInnerClassMapping, - paperMojangInnerClassMapping, - newInnerClassMapping - ) - } - - for (fieldMapping in mojangClassMapping.fieldMappings) { - targetMappings.createFieldMapping(fieldMapping.deobfuscatedSignature, fieldMapping.obfuscatedName) - } - for (methodMapping in mojangClassMapping.methodMappings) { - targetMappings.createMethodMapping(methodMapping.deobfuscatedSignature, methodMapping.obfuscatedName) - } - - // Pick up any changes made through mappings patches - if (paperMojangClassMapping != null) { - for (fieldMapping in paperMojangClassMapping.fieldMappings) { - val obfName = mojangClassMapping.fieldMappings - .firstOrNull { it.deobfuscatedSignature == fieldMapping.deobfuscatedSignature }?.obfuscatedName ?: continue - val deobfFieldType = fieldMapping.deobfuscatedSignature.type.orNull ?: continue - - targetMappings.getOrCreateFieldMapping(fieldMapping.deobfuscatedName, deobfFieldType).also { - it.deobfuscatedName = obfName - } - } - for (methodMapping in paperMojangClassMapping.methodMappings) { - val obfName = mojangClassMapping.methodMappings - .firstOrNull { it.deobfuscatedSignature == methodMapping.deobfuscatedSignature }?.obfuscatedName ?: continue - - targetMappings.getOrCreateMethodMapping(methodMapping.deobfuscatedSignature).also { - it.deobfuscatedName = obfName - } - } - } - } - } -} diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/GenerateSpigotMappings.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/GenerateSpigotMappings.kt deleted file mode 100644 index 220c761bc..000000000 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/GenerateSpigotMappings.kt +++ /dev/null @@ -1,312 +0,0 @@ -/* - * paperweight is a Gradle plugin for the PaperMC project. - * - * Copyright (c) 2023 Kyle Wood (DenWav) - * Contributors - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 only, no later versions. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package io.papermc.paperweight.tasks - -import io.papermc.paperweight.util.* -import io.papermc.paperweight.util.constants.* -import org.cadixdev.bombe.type.signature.FieldSignature -import org.cadixdev.bombe.type.signature.MethodSignature -import org.cadixdev.lorenz.MappingSet -import org.cadixdev.lorenz.merge.MappingSetMerger -import org.cadixdev.lorenz.merge.MappingSetMergerHandler -import org.cadixdev.lorenz.merge.MergeConfig -import org.cadixdev.lorenz.merge.MergeContext -import org.cadixdev.lorenz.merge.MergeResult -import org.cadixdev.lorenz.model.ClassMapping -import org.cadixdev.lorenz.model.FieldMapping -import org.cadixdev.lorenz.model.InnerClassMapping -import org.cadixdev.lorenz.model.MethodMapping -import org.cadixdev.lorenz.model.TopLevelClassMapping -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.tasks.CacheableTask -import org.gradle.api.tasks.InputFile -import org.gradle.api.tasks.OutputFile -import org.gradle.api.tasks.PathSensitive -import org.gradle.api.tasks.PathSensitivity -import org.gradle.api.tasks.TaskAction - -@CacheableTask -abstract class GenerateSpigotMappings : BaseTask() { - - @get:InputFile - @get:PathSensitive(PathSensitivity.NONE) - abstract val classMappings: RegularFileProperty - - @get:InputFile - @get:PathSensitive(PathSensitivity.NONE) - abstract val sourceMappings: RegularFileProperty - - @get:OutputFile - abstract val notchToSpigotMappings: RegularFileProperty - - @get:OutputFile - abstract val outputMappings: RegularFileProperty - - @get:OutputFile - abstract val spigotMemberMappings: RegularFileProperty - - @TaskAction - fun run() { - val spigotClassMappings = MappingFormats.CSRG.createReader(classMappings.path).use { it.read() } - - val sourceMappings = MappingFormats.TINY.read( - sourceMappings.path, - OBF_NAMESPACE, - DEOBF_NAMESPACE - ) - - val notchToSpigotSet = MappingSetMerger.create( - spigotClassMappings, - sourceMappings, - MergeConfig.builder() - .withMergeHandler(SpigotMappingsMergerHandler) - .build() - ).merge() - - val spigotToNamedSet = notchToSpigotSet.reverse().merge(sourceMappings) - - MappingFormats.TINY.write( - notchToSpigotSet, - notchToSpigotMappings.path, - OBF_NAMESPACE, - SPIGOT_NAMESPACE - ) - - MappingFormats.TINY.write( - spigotToNamedSet, - outputMappings.path, - SPIGOT_NAMESPACE, - DEOBF_NAMESPACE - ) - - val spigotMembers = createSpigotMemberMappings(sourceMappings, spigotClassMappings) - MappingFormats.CSRG.write(spigotMembers, spigotMemberMappings.path) - } -} - -object SpigotMappingsMergerHandler : MappingSetMergerHandler { - - // - // TOP LEVEL CLASS - // - - override fun mergeTopLevelClassMappings( - left: TopLevelClassMapping, - right: TopLevelClassMapping, - target: MappingSet, - context: MergeContext - ): MergeResult { - throw IllegalStateException("Unexpectedly merged class: ${left.fullObfuscatedName}") - } - - override fun mergeDuplicateTopLevelClassMappings( - left: TopLevelClassMapping, - right: TopLevelClassMapping, - rightContinuation: TopLevelClassMapping?, - target: MappingSet, - context: MergeContext - ): MergeResult { - // If both are provided, keep spigot - return MergeResult( - target.createTopLevelClassMapping(left.obfuscatedName, left.deobfuscatedName), - right - ) - } - - override fun addLeftTopLevelClassMapping( - left: TopLevelClassMapping, - target: MappingSet, - context: MergeContext - ): MergeResult { - throw IllegalStateException( - "Unexpected added class from Spigot: ${left.fullObfuscatedName} - ${left.fullDeobfuscatedName}" - ) - } - - override fun addRightTopLevelClassMapping( - right: TopLevelClassMapping, - target: MappingSet, - context: MergeContext - ): MergeResult { - // This is a mapping Spigot is totally missing - return MergeResult( - target.createTopLevelClassMapping(right.obfuscatedName, right.obfuscatedName), - right - ) - } - - // - // INNER CLASS - // - - override fun mergeInnerClassMappings( - left: InnerClassMapping, - right: InnerClassMapping, - target: ClassMapping<*, *>, - context: MergeContext - ): MergeResult { - throw IllegalStateException("Unexpectedly merged class: ${left.fullObfuscatedName}") - } - - override fun mergeDuplicateInnerClassMappings( - left: InnerClassMapping, - right: InnerClassMapping, - rightContinuation: InnerClassMapping?, - target: ClassMapping<*, *>, - context: MergeContext - ): MergeResult { - return MergeResult( - target.createInnerClassMapping(left.obfuscatedName, left.deobfuscatedName), - right - ) - } - - override fun addLeftInnerClassMapping( - left: InnerClassMapping, - target: ClassMapping<*, *>, - context: MergeContext - ): MergeResult { - throw IllegalStateException( - "Unexpected added class from Spigot: ${left.fullObfuscatedName} - ${left.fullDeobfuscatedName}" - ) - } - - override fun addRightInnerClassMapping( - right: InnerClassMapping, - target: ClassMapping<*, *>, - context: MergeContext - ): MergeResult { - // We want to get all of the inner classes from mojmap, but not the mojmap names - return MergeResult(target.createInnerClassMapping(right.obfuscatedName, right.obfuscatedName), right) - } - - // - // FIELD - // - - override fun mergeFieldMappings( - left: FieldMapping, - strictRight: FieldMapping?, - looseRight: FieldMapping?, - target: ClassMapping<*, *>, - context: MergeContext - ): FieldMapping { - throw IllegalStateException("Unexpectedly merged field: ${left.fullObfuscatedName}") - } - - override fun mergeDuplicateFieldMappings( - left: FieldMapping, - strictRightDuplicate: FieldMapping?, - looseRightDuplicate: FieldMapping?, - strictRightContinuation: FieldMapping?, - looseRightContinuation: FieldMapping?, - target: ClassMapping<*, *>, - context: MergeContext - ): FieldMapping { - val right = strictRightDuplicate ?: looseRightDuplicate ?: strictRightContinuation ?: looseRightContinuation ?: left - return target.createFieldMapping(right.signature, left.deobfuscatedName) - } - - override fun addLeftFieldMapping(left: FieldMapping, target: ClassMapping<*, *>, context: MergeContext): FieldMapping? { - throw IllegalStateException( - "Unexpected added field from Spigot: ${left.fullObfuscatedName} - ${left.fullDeobfuscatedName}" - ) - } - - // - // METHOD - // - - override fun mergeMethodMappings( - left: MethodMapping, - standardRight: MethodMapping?, - wiggledRight: MethodMapping?, - target: ClassMapping<*, *>, - context: MergeContext - ): MergeResult { - throw IllegalStateException("Unexpectedly merged method: $left") - } - - override fun mergeDuplicateMethodMappings( - left: MethodMapping, - strictRightDuplicate: MethodMapping?, - looseRightDuplicate: MethodMapping?, - strictRightContinuation: MethodMapping?, - looseRightContinuation: MethodMapping?, - target: ClassMapping<*, *>, - context: MergeContext - ): MergeResult { - val right = strictRightDuplicate ?: looseRightDuplicate ?: strictRightContinuation ?: looseRightContinuation ?: left - return MergeResult(target.createMethodMapping(left.signature, left.deobfuscatedName), right) - } - - override fun addLeftMethodMapping( - left: MethodMapping, - target: ClassMapping<*, *>, - context: MergeContext - ): MergeResult { - throw IllegalStateException( - "Unexpected added method from Spigot: ${left.fullObfuscatedName} - ${left.fullDeobfuscatedName}" - ) - } -} - -private fun createSpigotMemberMappings(mappings: MappingSet, spigotClassMappings: MappingSet): MappingSet { - val newMappings = MappingSet.create() - - for (topLevelClassMapping in mappings.topLevelClassMappings) { - val name = spigotClassMappings.getTopLevelClassMapping(topLevelClassMapping.obfuscatedName).orElse(topLevelClassMapping).deobfuscatedName - val newClassMappings = newMappings.createTopLevelClassMapping(name, name) - createSpigotMemberMappings(topLevelClassMapping, newClassMappings, spigotClassMappings) - } - - return newMappings -} - -private fun createSpigotMemberMappings(old: ClassMapping<*, *>, new: ClassMapping<*, *>, spigotClassMappings: MappingSet) { - for (innerClassMapping in old.innerClassMappings) { - val name = spigotClassMappings.getClassMapping(innerClassMapping.fullObfuscatedName) - .map { it.deobfuscatedName } - .orElse(innerClassMapping.obfuscatedName) - val newClassMappings = new.createInnerClassMapping(name, name) - createSpigotMemberMappings(innerClassMapping, newClassMappings, spigotClassMappings) - } - - for (fieldMapping in old.fieldMappings) { - new.createFieldMapping(FieldSignature(fieldMapping.obfuscatedName, fieldMapping.type.get()), fieldMapping.deobfuscatedName) - } - - for (methodMapping in old.methodMappings) { - if (methodMapping.deobfuscatedName.contains("$") || - methodMapping.deobfuscatedName == "" || - methodMapping.deobfuscatedName == "" - ) { - continue - } - - val desc = spigotClassMappings.deobfuscate(methodMapping.descriptor) - new.createMethodMapping(MethodSignature(methodMapping.obfuscatedName, desc)).also { - it.deobfuscatedName = methodMapping.deobfuscatedName - } - } -} diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/IncludeMappings.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/IncludeMappings.kt deleted file mode 100644 index 7e99f8616..000000000 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/IncludeMappings.kt +++ /dev/null @@ -1,66 +0,0 @@ -/* - * paperweight is a Gradle plugin for the PaperMC project. - * - * Copyright (c) 2023 Kyle Wood (DenWav) - * Contributors - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 only, no later versions. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package io.papermc.paperweight.tasks - -import io.papermc.paperweight.util.* -import kotlin.io.path.* -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.provider.Property -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.InputFile -import org.gradle.api.tasks.OutputFile -import org.gradle.api.tasks.TaskAction - -abstract class IncludeMappings : BaseTask() { - @get:InputFile - abstract val inputJar: RegularFileProperty - - @get:InputFile - abstract val mappings: RegularFileProperty - - @get:Input - abstract val mappingsDest: Property - - @get:OutputFile - abstract val outputJar: RegularFileProperty - - override fun init() { - super.init() - outputJar.convention(defaultOutput()) - } - - @TaskAction - fun addMappings() { - outputJar.path.parent.createDirectories() - inputJar.path.copyTo(outputJar.path, overwrite = true) - outputJar.path.openZip().use { fs -> - val dest = fs.getPath(mappingsDest.get()) - dest.parent.createDirectories() - mappings.path.copyTo(dest) - - fs.modifyManifest { - mainAttributes.putValue("Included-Mappings-Hash", mappings.path.hashFile(HashingAlgorithm.SHA256).asHexString().uppercase()) - } - } - } -} diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/PatchMappings.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/PatchMappings.kt deleted file mode 100644 index 48aa69336..000000000 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/PatchMappings.kt +++ /dev/null @@ -1,108 +0,0 @@ -/* - * paperweight is a Gradle plugin for the PaperMC project. - * - * Copyright (c) 2023 Kyle Wood (DenWav) - * Contributors - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 only, no later versions. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package io.papermc.paperweight.tasks - -import io.papermc.paperweight.util.* -import java.nio.file.Path -import kotlin.io.path.* -import net.fabricmc.lorenztiny.TinyMappingFormat -import org.cadixdev.lorenz.MappingSet -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.provider.Property -import org.gradle.api.tasks.* - -abstract class PatchMappings : BaseTask() { - - @get:InputFile - @get:PathSensitive(PathSensitivity.NONE) - abstract val inputMappings: RegularFileProperty - - @get:Optional - @get:InputFile - @get:PathSensitive(PathSensitivity.NONE) - abstract val patch: RegularFileProperty - - @get:Input - abstract val fromNamespace: Property - - @get:Input - abstract val toNamespace: Property - - @get:OutputFile - abstract val outputMappings: RegularFileProperty - - @TaskAction - fun run() { - appendPatch( - inputMappings.path, - patch.pathOrNull, - outputMappings.path - ) - } - - private fun appendPatch(input: Path, patch: Path?, output: Path) { - val mappings = MappingFormats.TINY.readCommented( - input, - fromNamespace.get(), - toNamespace.get() - ) - patch?.let { - MappingFormats.TINY.readCommented( - it, - fromNamespace.get(), - toNamespace.get(), - mappings - ) - } - - MappingFormats.TINY.write(mappings, output, fromNamespace.get(), toNamespace.get()) - } - - private fun TinyMappingFormat.readCommented( - mappings: Path, - fromNamespace: String, - toNamespace: String, - into: MappingSet? = null - ): MappingSet { - val temp = createTempFile("patch", "tiny") - try { - val comment = commentRegex() - // tiny format doesn't allow comments, so we manually remove them - // The tiny mappings reader also doesn't have a InputStream or Reader input... - mappings.useLines { lines -> - temp.bufferedWriter().use { writer -> - for (line in lines) { - val newLine = comment.replace(line, "") - if (newLine.isNotBlank()) { - writer.appendLine(newLine) - } - } - } - } - return into?.let { read(it, temp, fromNamespace, toNamespace) } - ?: read(temp, fromNamespace, toNamespace) - } finally { - temp.deleteForcefully() - } - } -} diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/RelocateClassNameConstants.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/RelocateClassNameConstants.kt deleted file mode 100644 index 48ff178a7..000000000 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/RelocateClassNameConstants.kt +++ /dev/null @@ -1,145 +0,0 @@ -/* - * paperweight is a Gradle plugin for the PaperMC project. - * - * Copyright (c) 2023 Kyle Wood (DenWav) - * Contributors - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 only, no later versions. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package io.papermc.paperweight.tasks - -import io.papermc.paperweight.util.* -import java.nio.file.Path -import kotlin.io.path.* -import org.gradle.api.Action -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.provider.ListProperty -import org.gradle.api.provider.Property -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.InputFile -import org.gradle.api.tasks.Nested -import org.gradle.api.tasks.Optional -import org.gradle.api.tasks.OutputFile -import org.gradle.api.tasks.TaskAction -import org.gradle.kotlin.dsl.* -import org.objectweb.asm.ClassVisitor -import org.objectweb.asm.MethodVisitor -import org.objectweb.asm.Opcodes -import org.objectweb.asm.tree.ClassNode - -@Suppress("LeakingThis") -abstract class RelocateClassNameConstants : BaseTask() { - @get:InputFile - abstract val inputJar: RegularFileProperty - - @get:OutputFile - abstract val outputJar: RegularFileProperty - - @get:Nested - @get:Optional - abstract val relocations: ListProperty - - @get:Input - @get:Optional - abstract val processOnly: ListProperty - - fun relocate(fromPackage: String, toPackage: String, op: Action) { - relocations.add( - objects.newInstance().apply { - this.fromPackage.set(fromPackage) - this.toPackage.set(toPackage) - op.execute(this) - } - ) - } - - init { - outputJar.convention(defaultOutput()) - processOnly.convention( - listOf( - "org/bukkit/craftbukkit/**/*.class", - "org/bukkit/craftbukkit/*.class" - ) - ) - } - - @TaskAction - fun run() { - outputJar.path.deleteForcefully() - outputJar.path.parent.createDirectories() - val relocations = relocations.get().map { - RelocationWrapper(Relocation(null, it.fromPackage.get(), it.toPackage.get(), emptyList())) - } - outputJar.path.writeZip().use { outputFs -> - inputJar.path.openZip().use { inputFs -> - val includes = processOnly.getOrElse(emptyList()).map { - inputFs.getPathMatcher("glob:${if (it.startsWith('/')) it else "/$it"}") - } - JarProcessing.processJar( - inputFs, - outputFs, - object : JarProcessing.ClassProcessor.VisitorBased { - override fun shouldProcess(file: Path): Boolean = - includes.isEmpty() || includes.any { it.matches(file) } - - override fun processClass(node: ClassNode, parent: ClassVisitor, classNodeCache: ClassNodeCache): ClassVisitor = - ConstantRelocatingClassVisitor(parent, relocations) - } - ) - } - } - } - - private class ConstantRelocatingClassVisitor( - parent: ClassVisitor, - private val relocations: List - ) : ClassVisitor(Opcodes.ASM9, parent) { - override fun visitMethod( - access: Int, - name: String?, - descriptor: String?, - signature: String?, - exceptions: Array? - ): MethodVisitor { - return object : MethodVisitor(Opcodes.ASM9, super.visitMethod(access, name, descriptor, signature, exceptions)) { - override fun visitLdcInsn(value: Any?) { - if (value is String) { - var v: String = value - for (relocation in relocations) { - if (v.startsWith(relocation.fromDot)) { - v = v.replace(relocation.fromDot, relocation.toDot) - } else if (v.startsWith(relocation.fromSlash)) { - v = v.replace(relocation.fromSlash, relocation.toSlash) - } - } - super.visitLdcInsn(v) - } else { - super.visitLdcInsn(value) - } - } - } - } - } - - abstract class RelocationInput { - @get:Input - abstract val fromPackage: Property - - @get:Input - abstract val toPackage: Property - } -} diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/SpigotRemapJar.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/SpigotRemapJar.kt deleted file mode 100644 index 7abe3c0fd..000000000 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/SpigotRemapJar.kt +++ /dev/null @@ -1,179 +0,0 @@ -/* - * paperweight is a Gradle plugin for the PaperMC project. - * - * Copyright (c) 2023 Kyle Wood (DenWav) - * Contributors - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 only, no later versions. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package io.papermc.paperweight.tasks - -import io.papermc.paperweight.PaperweightException -import io.papermc.paperweight.util.* -import io.papermc.paperweight.util.constants.* -import kotlin.io.path.* -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.provider.Property -import org.gradle.api.tasks.* - -@CacheableTask -abstract class SpigotRemapJar : JavaLauncherTask() { - - @get:Classpath - abstract val inputJar: RegularFileProperty - - @get:InputFile - @get:PathSensitive(PathSensitivity.NONE) - abstract val classMappings: RegularFileProperty - - @get:InputFile - @get:PathSensitive(PathSensitivity.NONE) - abstract val memberMappings: RegularFileProperty - - @get:Input - abstract val mcVersion: Property - - @get:InputFile - @get:PathSensitive(PathSensitivity.NONE) - abstract val accessTransformers: RegularFileProperty - - @get:Classpath - abstract val specialSourceJar: RegularFileProperty - - @get:Classpath - abstract val specialSource2Jar: RegularFileProperty - - @get:Input - abstract val classMapCommand: Property - - @get:Input - abstract val memberMapCommand: Property - - @get:Input - abstract val finalMapCommand: Property - - @get:OutputFile - abstract val outputJar: RegularFileProperty - - override fun init() { - super.init() - - outputJar.convention(defaultOutput()) - } - - @TaskAction - fun run() { - val inputJarPath = inputJar.path.absolutePathString() - - val outputJarFile = outputJar.path - val outputJarPath = outputJarFile.absolutePathString() - - val classJarFile = outputJarFile.resolveSibling(outputJarFile.name + ".classes") - val membersJarFile = outputJarFile.resolveSibling(outputJarFile.name + ".members") - val classJarPath = classJarFile.absolutePathString() - val membersJarPath = membersJarFile.absolutePathString() - - val classMappingPath = classMappings.path.absolutePathString() - val accessTransformersPath = accessTransformers.path.absolutePathString() - - val spigotMembersPath = memberMappings.path.absolutePathString() - - val work = temporaryDir.toPath() - - val spigotEmptyMappings = layout.cache.resolve("spigot-empty-package-mappings.csrg") - spigotEmptyMappings.writeText("") - - try { - try { - val logFile = layout.cache.resolve(paperTaskOutput("class.log")) - logFile.deleteForcefully() - launcher.runJar( - objects.fileCollection().from(specialSource2Jar), - workingDir = work, - logFile = logFile, - args = doReplacements(classMapCommand.get(), inputJarPath, classMappingPath, classJarPath) { - // ignore excludes, we actually want to map every class - it != "-e" - } - ) - } catch (e: Exception) { - throw PaperweightException("Failed to apply class mappings", e) - } - - try { - val logFile = layout.cache.resolve(paperTaskOutput("member.log")) - logFile.deleteForcefully() - launcher.runJar( - objects.fileCollection().from(specialSource2Jar), - workingDir = work, - logFile = logFile, - args = doReplacements(memberMapCommand.get(), classJarPath, spigotMembersPath, membersJarPath) - ) - } catch (e: Exception) { - throw PaperweightException("Failed to apply member mappings", e) - } - - try { - val logFile = layout.cache.resolve(paperTaskOutput("final.log")) - logFile.deleteForcefully() - launcher.runJar( - objects.fileCollection().from(specialSourceJar), - workingDir = work, - logFile = logFile, - args = doReplacements( - finalMapCommand.get(), - membersJarPath, - accessTransformersPath, - spigotEmptyMappings.absolutePathString(), - outputJarPath - ) - ) - } catch (e: Exception) { - throw PaperweightException("Failed to create remapped jar", e) - } - } finally { - classJarFile.deleteForcefully() - membersJarFile.deleteForcefully() - spigotEmptyMappings.deleteForcefully() - } - } - - private val indexReg = Regex("\\{(\\d)}") - private fun doReplacements(command: String, vararg values: String, filter: ((String) -> Boolean)? = null): Array { - var skipNext = false - return command.split(" ").let { it.subList(3, it.size) } - .filter { - if (skipNext) { - skipNext = false - return@filter false - } else if (filter != null && !filter(it)) { - skipNext = true - return@filter false - } else { - return@filter true - } - } - .map { - val index = indexReg.matchEntire(it)?.groupValues?.get(1)?.toInt() - return@map if (index != null) { - values[index] - } else { - it - } - }.toTypedArray() - } -} diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/UnpackSpigotBuildData.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/UnpackSpigotBuildData.kt deleted file mode 100644 index 6fbc2bd20..000000000 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/UnpackSpigotBuildData.kt +++ /dev/null @@ -1,86 +0,0 @@ -/* - * paperweight is a Gradle plugin for the PaperMC project. - * - * Copyright (c) 2023 Kyle Wood (DenWav) - * Contributors - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 only, no later versions. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 - * USA - */ - -package io.papermc.paperweight.tasks - -import io.papermc.paperweight.util.* -import java.nio.file.Path -import kotlin.io.path.* -import org.gradle.api.file.RegularFileProperty -import org.gradle.api.tasks.InputFile -import org.gradle.api.tasks.OutputFile -import org.gradle.api.tasks.TaskAction - -abstract class UnpackSpigotBuildData : BaseTask() { - @get:InputFile - abstract val buildDataZip: RegularFileProperty - - @get:OutputFile - abstract val buildDataInfoFile: RegularFileProperty - - @get:OutputFile - abstract val excludesFile: RegularFileProperty - - @get:OutputFile - abstract val atFile: RegularFileProperty - - @get:OutputFile - abstract val classMappings: RegularFileProperty - - @get:OutputFile - abstract val specialSourceJar: RegularFileProperty - - @get:OutputFile - abstract val specialSource2Jar: RegularFileProperty - - override fun init() { - buildDataInfoFile.convention(defaultOutput("spigot-build-data-info", "json")) - excludesFile.convention(defaultOutput("spigot-excludes", "exclude")) - atFile.convention(defaultOutput("spigot-ats", "at")) - classMappings.convention(defaultOutput("spigot-class-mapping", "csrg")) - specialSourceJar.convention(defaultOutput("special-source", "jar")) - specialSource2Jar.convention(defaultOutput("special-source-2", "jar")) - } - - @TaskAction - fun run() { - buildDataZip.path.openZip().use { - val root = it.getPath("/") - root.resolve("info.json") - .copyTo(buildDataInfoFile.path.createParentDirectories(), overwrite = true) - val mappings = root.resolve("mappings") - bukkitFileFrom(mappings, "exclude") - .copyTo(excludesFile.path.createParentDirectories(), overwrite = true) - bukkitFileFrom(mappings, "at") - .copyTo(atFile.path.createParentDirectories(), overwrite = true) - bukkitFileFrom(mappings, "csrg") - .copyTo(classMappings.path.createParentDirectories(), overwrite = true) - root.resolve("bin/SpecialSource.jar") - .copyTo(specialSourceJar.path.createParentDirectories(), overwrite = true) - root.resolve("bin/SpecialSource-2.jar") - .copyTo(specialSource2Jar.path.createParentDirectories(), overwrite = true) - } - } - - private fun bukkitFileFrom(dir: Path, extension: String): Path = - dir.useDirectoryEntries { it.filter { f -> f.name.endsWith(extension) }.single() } -} diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/mache/RunCodebook.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/mache/RunCodebook.kt index 70212048d..a1a2ea78c 100644 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/mache/RunCodebook.kt +++ b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/tasks/mache/RunCodebook.kt @@ -40,12 +40,8 @@ abstract class RunCodebook : JavaLauncherTask() { @get:InputFile abstract val serverJar: RegularFileProperty - @get:PathSensitive(PathSensitivity.NONE) - @get:InputFile - abstract val serverMappings: RegularFileProperty - @get:Input - abstract val remapperArgs: ListProperty + abstract val codebookArgs: ListProperty @get:Classpath abstract val codebookClasspath: ConfigurableFileCollection @@ -53,13 +49,6 @@ abstract class RunCodebook : JavaLauncherTask() { @get:CompileClasspath abstract val minecraftClasspath: ConfigurableFileCollection - @get:Classpath - abstract val remapperClasspath: ConfigurableFileCollection - - @get:PathSensitive(PathSensitivity.NONE) - @get:InputFiles - abstract val paramMappings: ConfigurableFileCollection - @get:Classpath abstract val constants: ConfigurableFileCollection @@ -72,11 +61,11 @@ abstract class RunCodebook : JavaLauncherTask() { launcher.get(), codebookClasspath, outputJar.path, - remapperArgs.get(), + codebookArgs.get(), temporaryDir.toPath(), - remapperClasspath, - serverMappings.path, - paramMappings.singleFile.toPath(), + null, + null, + null, constants.files.singleOrNull()?.toPath(), serverJar.path, minecraftClasspath.files.map { it.toPath() } @@ -90,9 +79,9 @@ fun runCodebook( outputJar: Path, remapperArgs: List, tempDir: Path, - remapperClasspath: FileCollection, - serverMappings: Path, - paramMappings: Path, + remapperClasspath: FileCollection?, + serverMappings: Path?, + paramMappings: Path?, constants: Path?, serverJar: Path, minecraftClasspath: List, @@ -106,10 +95,18 @@ fun runCodebook( remapperArgs.forEach { arg -> args += arg .replace(Regex("\\{tempDir}")) { tempDir.absolutePathString() } - .replace(Regex("\\{remapperFile}")) { remapperClasspath.singleFile.absolutePath } - .replace(Regex("\\{mappingsFile}")) { serverMappings.absolutePathString() } - .replace(Regex("\\{paramsFile}")) { paramMappings.absolutePathString() } - .replace(Regex("\\{constantsFile}")) { constants!!.absolutePathString() } + .replace(Regex("\\{remapperFile}")) { + remapperClasspath?.singleFile?.absolutePath ?: error("{remapperFile} in args, but no remapperClasspath provided") + } + .replace(Regex("\\{mappingsFile}")) { + serverMappings?.absolutePathString() ?: error("{mappingsFile} in args, but no serverMappings provided") + } + .replace(Regex("\\{paramsFile}")) { + paramMappings?.absolutePathString() ?: error("{paramsFile} in args, but no paramMappings provided") + } + .replace(Regex("\\{constantsFile}")) { + constants?.absolutePathString() ?: error("{constantsFile} in args, but no constants provided") + } .replace(Regex("\\{output}")) { outputJar.absolutePathString() } .replace(Regex("\\{input}")) { serverJar.absolutePathString() } .replace(Regex("\\{inputClasspath}")) { minecraftClasspath.joinToString(":") { it.absolutePathString() } } diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/data/mache/MacheDependencies.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/data/mache/MacheDependencies.kt index 630003ed0..7aadb4041 100644 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/data/mache/MacheDependencies.kt +++ b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/data/mache/MacheDependencies.kt @@ -24,8 +24,8 @@ package io.papermc.paperweight.util.data.mache data class MacheDependencies( val codebook: List, - val paramMappings: List, + val paramMappings: List?, val constants: List, - val remapper: List, + val remapper: List?, val decompiler: List, ) diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/data/mache/MacheMeta.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/data/mache/MacheMeta.kt index cb613557c..ee8c0f445 100644 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/data/mache/MacheMeta.kt +++ b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/data/mache/MacheMeta.kt @@ -62,7 +62,7 @@ data class MacheMeta( } named(MACHE_PARAM_MAPPINGS_CONFIG) { defaultDependencies { - macheDeps.paramMappings.forEach { + macheDeps.paramMappings?.forEach { add(project.dependencies.create(it.toMavenString())) } } @@ -76,7 +76,7 @@ data class MacheMeta( } named(MACHE_REMAPPER_CONFIG) { defaultDependencies { - macheDeps.remapper.forEach { + macheDeps.remapper?.forEach { add(project.dependencies.create(it.toMavenString())) } } diff --git a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/utils.kt b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/utils.kt index 4d653072d..2a4246f24 100644 --- a/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/utils.kt +++ b/paperweight-lib/src/main/kotlin/io/papermc/paperweight/util/utils.kt @@ -381,7 +381,7 @@ fun ByteArray.asHexString(): String { fun JavaToolchainService.defaultJavaLauncher(project: Project): Provider { // If the java plugin isn't applied, or no toolchain value was set val fallback = launcherFor { - languageVersion.set(JavaLanguageVersion.of(21)) + languageVersion.set(JavaLanguageVersion.of(25)) } val ext = project.extensions.findByType() ?: return fallback diff --git a/paperweight-userdev/src/main/kotlin/io/papermc/paperweight/userdev/internal/setup/DevBundles.kt b/paperweight-userdev/src/main/kotlin/io/papermc/paperweight/userdev/internal/setup/DevBundles.kt index 7cf316fa4..e2421ca81 100644 --- a/paperweight-userdev/src/main/kotlin/io/papermc/paperweight/userdev/internal/setup/DevBundles.kt +++ b/paperweight-userdev/src/main/kotlin/io/papermc/paperweight/userdev/internal/setup/DevBundles.kt @@ -26,6 +26,7 @@ import io.papermc.paperweight.PaperweightException import io.papermc.paperweight.tasks.* import io.papermc.paperweight.userdev.internal.setup.v2.DevBundleV2 import io.papermc.paperweight.userdev.internal.setup.v5.DevBundleV5 +import io.papermc.paperweight.userdev.internal.setup.v7.DevBundleV7 import io.papermc.paperweight.util.* import java.nio.file.Path import kotlin.io.path.* @@ -35,8 +36,9 @@ private val supported = mapOf( 3 to DevBundleV5.Config::class, // up to 1.20.4 4 to DevBundleV5.Config::class, // 1.20.5, early 1.20.6 5 to DevBundleV5.Config::class, // 1.20.6+ (nullable mojangApiCoordinates) - 6 to GenerateDevBundle.DevBundleConfig::class, // Post-repo-restructure 1.21.4, early 1.21.5 - 7 to GenerateDevBundle.DevBundleConfig::class, // 1.21.5+ + 6 to DevBundleV7.Config::class, // Post-repo-restructure 1.21.4, early 1.21.5 + 7 to DevBundleV7.Config::class, // 1.21.5+ + 8 to GenerateDevBundle.DevBundleConfig::class, // 26.1+ ) fun readBundleInfo(bundleZip: Path): BundleInfo { diff --git a/paperweight-userdev/src/main/kotlin/io/papermc/paperweight/userdev/internal/setup/SetupHandlerImpl.kt b/paperweight-userdev/src/main/kotlin/io/papermc/paperweight/userdev/internal/setup/SetupHandlerImpl.kt index d91eef9c5..07b0617b7 100644 --- a/paperweight-userdev/src/main/kotlin/io/papermc/paperweight/userdev/internal/setup/SetupHandlerImpl.kt +++ b/paperweight-userdev/src/main/kotlin/io/papermc/paperweight/userdev/internal/setup/SetupHandlerImpl.kt @@ -199,11 +199,7 @@ class SetupHandlerImpl( } override fun extractReobfMappings(output: Path) { - bundle.config.reobfMappingsFile?.let { location -> - bundle.zip.openZipSafe().use { fs -> - fs.getPath(location).copyTo(output, true) - } - } + // TODO } private fun macheMeta(): MacheMeta = requireNotNull(macheMeta) { "Mache meta is not setup yet" } diff --git a/paperweight-userdev/src/main/kotlin/io/papermc/paperweight/userdev/internal/setup/v2/SetupHandlerImplV2.kt b/paperweight-userdev/src/main/kotlin/io/papermc/paperweight/userdev/internal/setup/v2/SetupHandlerImplV2.kt index a542a48c7..3d168a618 100644 --- a/paperweight-userdev/src/main/kotlin/io/papermc/paperweight/userdev/internal/setup/v2/SetupHandlerImplV2.kt +++ b/paperweight-userdev/src/main/kotlin/io/papermc/paperweight/userdev/internal/setup/v2/SetupHandlerImplV2.kt @@ -32,6 +32,7 @@ import io.papermc.paperweight.userdev.internal.setup.SetupHandler import io.papermc.paperweight.userdev.internal.setup.UserdevSetup import io.papermc.paperweight.userdev.internal.setup.UserdevSetupTask import io.papermc.paperweight.userdev.internal.setup.action.* +import io.papermc.paperweight.userdev.internal.setup.action.GenerateMappingsAction import io.papermc.paperweight.util.* import io.papermc.paperweight.util.constants.* import java.nio.file.Path diff --git a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/extension/SpigotExtension.kt b/paperweight-userdev/src/main/kotlin/io/papermc/paperweight/userdev/internal/setup/v7/DevBundleV7.kt similarity index 66% rename from paperweight-core/src/main/kotlin/io/papermc/paperweight/core/extension/SpigotExtension.kt rename to paperweight-userdev/src/main/kotlin/io/papermc/paperweight/userdev/internal/setup/v7/DevBundleV7.kt index db994117d..48dda242b 100644 --- a/paperweight-core/src/main/kotlin/io/papermc/paperweight/core/extension/SpigotExtension.kt +++ b/paperweight-userdev/src/main/kotlin/io/papermc/paperweight/userdev/internal/setup/v7/DevBundleV7.kt @@ -20,13 +20,18 @@ * USA */ -package io.papermc.paperweight.core.extension +package io.papermc.paperweight.userdev.internal.setup.v7 -import org.gradle.api.provider.Property +import io.papermc.paperweight.util.MavenDep -interface SpigotExtension { - - val buildDataRef: Property - val packageVersion: Property - val enabled: Property +object DevBundleV7 { + data class Config( + val minecraftVersion: String, + val mache: MavenDep, + val patchDir: String, + val reobfMappingsFile: String?, + val mojangMappedPaperclipFile: String, + val libraryRepositories: List, + val pluginRemapArgs: List, + ) } diff --git a/paperweight-userdev/src/main/kotlin/io/papermc/paperweight/userdev/internal/setup/v7/SetupHandlerImplV7.kt b/paperweight-userdev/src/main/kotlin/io/papermc/paperweight/userdev/internal/setup/v7/SetupHandlerImplV7.kt new file mode 100644 index 000000000..5acc20395 --- /dev/null +++ b/paperweight-userdev/src/main/kotlin/io/papermc/paperweight/userdev/internal/setup/v7/SetupHandlerImplV7.kt @@ -0,0 +1,276 @@ +/* + * paperweight is a Gradle plugin for the PaperMC project. + * + * Copyright (c) 2023 Kyle Wood (DenWav) + * Contributors + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 only, no later versions. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +package io.papermc.paperweight.userdev.internal.setup.v7 + +import io.papermc.paperweight.userdev.internal.action.FileCollectionValue +import io.papermc.paperweight.userdev.internal.action.StringValue +import io.papermc.paperweight.userdev.internal.action.WorkDispatcher +import io.papermc.paperweight.userdev.internal.action.fileValue +import io.papermc.paperweight.userdev.internal.action.javaLauncherValue +import io.papermc.paperweight.userdev.internal.action.stringListValue +import io.papermc.paperweight.userdev.internal.setup.BundleInfo +import io.papermc.paperweight.userdev.internal.setup.SetupHandler +import io.papermc.paperweight.userdev.internal.setup.UserdevSetup +import io.papermc.paperweight.userdev.internal.setup.UserdevSetupTask +import io.papermc.paperweight.userdev.internal.setup.action.ApplyDevBundlePatchesAction +import io.papermc.paperweight.userdev.internal.setup.action.ExtractFromBundlerAction +import io.papermc.paperweight.userdev.internal.setup.action.RunCodebookAction +import io.papermc.paperweight.userdev.internal.setup.action.RunPaperclipAction +import io.papermc.paperweight.userdev.internal.setup.action.SetupMacheSourcesAction +import io.papermc.paperweight.userdev.internal.setup.action.VanillaServerDownloads +import io.papermc.paperweight.util.* +import io.papermc.paperweight.util.constants.* +import io.papermc.paperweight.util.data.mache.* +import java.nio.file.Path +import kotlin.io.path.* +import org.gradle.api.artifacts.DependencySet +import org.gradle.api.file.FileCollection +import org.gradle.api.provider.Property +import org.gradle.kotlin.dsl.* + +class SetupHandlerImplV7( + private val parameters: UserdevSetup.Parameters, + private val bundle: BundleInfo, +) : SetupHandler { + private var macheMeta: MacheMeta? = null + + private fun createDispatcher(context: SetupHandler.ExecutionContext): WorkDispatcher { + val dispatcher = WorkDispatcher.create(parameters.cache.path) + dispatcher.overrideTerminalInputHash(parameters.bundleZipHash.get()) + + val javaLauncher = javaLauncherValue(context.javaLauncher) + val mcVer = StringValue(bundle.config.minecraftVersion) + val bundleZip = fileValue(bundle.zip) + dispatcher.provided( + javaLauncher, + mcVer, + bundleZip, + ) + + val vanillaDownloads = dispatcher.register( + "vanillaServerDownloads", + VanillaServerDownloads( + mcVer, + dispatcher.outputFile("vanillaServer.jar"), + dispatcher.outputFile("mojangServerMappings.txt"), + parameters.downloadService.get(), + ) + ) + + val applyPaperclip = dispatcher.register( + "applyPaperclipPatch", + RunPaperclipAction( + javaLauncher, + bundleZip, + StringValue(bundle.config.mojangMappedPaperclipFile), + dispatcher.outputFile("output.jar"), + vanillaDownloads.serverJar, + mcVer, + ) + ) + dispatcher.provided(applyPaperclip.paperclipPath) + + val extract = dispatcher.register( + "extractFromBundler", + ExtractFromBundlerAction( + vanillaDownloads.serverJar, + dispatcher.outputFile("vanillaServer.jar"), + dispatcher.outputDir("minecraftLibraries"), + ) + ) + + val remap = dispatcher.register( + "remapMinecraft", + RunCodebookAction( + javaLauncher, + stringListValue(macheMeta().remapperArgs), + extract.vanillaServerJar, + extract.minecraftLibraryJars, + vanillaDownloads.serverMappings, + FileCollectionValue(context.macheParamMappingsConfig), + FileCollectionValue(context.macheConstantsConfig), + FileCollectionValue(context.macheCodebookConfig), + FileCollectionValue(context.macheRemapperConfig), + dispatcher.outputFile("output.jar"), + ) + ) + dispatcher.provided( + remap.minecraftRemapArgs, + remap.paramMappings, + remap.constants, + remap.codebook, + remap.remapper, + ) + + val macheSources = dispatcher.register( + "setupMacheSources", + SetupMacheSourcesAction( + javaLauncher, + remap.outputJar, + dispatcher.outputFile("output.zip"), + extract.minecraftLibraryJars, + stringListValue(macheMeta().decompilerArgs), + FileCollectionValue(context.macheDecompilerConfig), + FileCollectionValue(context.macheConfig), + ) + ) + dispatcher.provided( + macheSources.decompileArgs, + macheSources.decompiler, + macheSources.mache, + ) + + val applyPatches = dispatcher.register( + "applyDevBundlePatches", + ApplyDevBundlePatchesAction( + macheSources.outputJar, + bundleZip, + StringValue(bundle.config.patchDir), + dispatcher.outputFile("output.jar"), + applyPaperclip.outputJar, + ) + ) + dispatcher.provided(applyPatches.patchesPath) + + return dispatcher + } + + override fun populateCompileConfiguration( + context: SetupHandler.ConfigurationContext, + dependencySet: DependencySet, + injectServerJar: Property + ) { + if (injectServerJar.get()) { + dependencySet.add(context.dependencyFactory.create(context.layout.files(context.setupTask.flatMap { it.mappedServerJar }))) + } + dependencySet.add(context.dependencyFactory.create(context.devBundleCoordinates)) + } + + override fun populateRuntimeConfiguration( + context: SetupHandler.ConfigurationContext, + dependencySet: DependencySet, + injectServerJar: Property + ) { + populateCompileConfiguration(context, dependencySet, injectServerJar) + } + + @Volatile + private var completedOutput: SetupHandler.ArtifactsResult? = null + + @Synchronized + override fun generateArtifacts(context: SetupHandler.ExecutionContext): SetupHandler.ArtifactsResult { + if (completedOutput != null) { + return requireNotNull(completedOutput) + } + + // If the config cache is reused then the mache config may not be populated + setupMacheMeta(context.macheConfig) + + val dispatcher = createDispatcher(context) + val request = if (parameters.genSources.get()) { + dispatcher.registered("applyDevBundlePatches").outputJar + } else { + dispatcher.registered("applyPaperclipPatch").outputJar + } + context.withProgressLogger { progressLogger -> + dispatcher.dispatch(request) { + progressLogger.progress(it) + } + } + return SetupHandler.ArtifactsResult(request.get(), null) + .also { completedOutput = it } + } + + override fun extractReobfMappings(output: Path) { + bundle.config.reobfMappingsFile?.let { location -> + bundle.zip.openZipSafe().use { fs -> + fs.getPath(location).copyTo(output, true) + } + } + } + + private fun macheMeta(): MacheMeta = requireNotNull(macheMeta) { "Mache meta is not setup yet" } + + private fun setupMacheMeta(macheFiles: FileCollection) { + if (macheMeta == null) { + synchronized(this) { + macheMeta = macheFiles.resolveMacheMeta() + } + } + } + + override fun afterEvaluate(context: SetupHandler.ConfigurationContext) { + super.afterEvaluate(context) + setupMacheMeta(context.project.configurations.getByName(MACHE_CONFIG)) + + val configurations = context.project.configurations + + val macheCodebook = configurations.register(MACHE_CODEBOOK_CONFIG) { + isTransitive = false + } + val macheRemapper = configurations.register(MACHE_REMAPPER_CONFIG) { + isTransitive = false + } + val macheDecompiler = configurations.register(MACHE_DECOMPILER_CONFIG) { + isTransitive = false + } + val macheParamMappings = configurations.register(MACHE_PARAM_MAPPINGS_CONFIG) { + isTransitive = false + } + val macheConstants = configurations.register(MACHE_CONSTANTS_CONFIG) { + isTransitive = false + } + + context.project.tasks.withType(UserdevSetupTask::class).configureEach { + macheCodebookConfig.from(macheCodebook) + macheRemapperConfig.from(macheRemapper) + macheDecompilerConfig.from(macheDecompiler) + macheParamMappingsConfig.from(macheParamMappings) + macheConstantsConfig.from(macheConstants) + } + + macheMeta().addDependencies(context.project) + macheMeta().addRepositories(context.project) + } + + override val minecraftVersion: String + get() = bundle.config.minecraftVersion + + override val pluginRemapArgs: List + get() = bundle.config.pluginRemapArgs + + override val paramMappings: MavenDep? + get() = null + + override val decompiler: MavenDep? + get() = null + + override val remapper: MavenDep? + get() = null + + override val mache: MavenDep + get() = bundle.config.mache + + override val libraryRepositories: List + get() = bundle.config.libraryRepositories +}