From 6b35e44355e4091d90aabd4a8eeb43e8a82d4929 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Thu, 10 Jun 2021 18:13:57 -0700 Subject: [PATCH] Better support legacy Minecraft versions - On versions without the `add-plugin` command line argument, just copy jars into the plugins folder. - Paper disabled the server gui by default from 1.8 through 1.14, so we do not need to supply that argument for those versions. --- .../kotlin/xyz/jpenilla/runpaper/Constants.kt | 2 +- .../runpaper/service/PaperclipService.kt | 3 +- .../jpenilla/runpaper/task/RunServerTask.kt | 92 +++++++++++++++++-- 3 files changed, 89 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/xyz/jpenilla/runpaper/Constants.kt b/src/main/kotlin/xyz/jpenilla/runpaper/Constants.kt index bd737fd..d44d7dc 100644 --- a/src/main/kotlin/xyz/jpenilla/runpaper/Constants.kt +++ b/src/main/kotlin/xyz/jpenilla/runpaper/Constants.kt @@ -18,7 +18,7 @@ package xyz.jpenilla.runpaper internal object Constants { const val RUN_PAPER = "RunPaper" - const val TASK_GROUP = "run paper" + const val TASK_GROUP = "Run Paper" const val GRADLE_CACHES_DIRECTORY_NAME = "caches" object Plugins { diff --git a/src/main/kotlin/xyz/jpenilla/runpaper/service/PaperclipService.kt b/src/main/kotlin/xyz/jpenilla/runpaper/service/PaperclipService.kt index 7dd862f..2f07825 100644 --- a/src/main/kotlin/xyz/jpenilla/runpaper/service/PaperclipService.kt +++ b/src/main/kotlin/xyz/jpenilla/runpaper/service/PaperclipService.kt @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.SerializationFeature import com.fasterxml.jackson.databind.json.JsonMapper import com.fasterxml.jackson.module.kotlin.kotlinModule import com.fasterxml.jackson.module.kotlin.readValue +import org.gradle.api.InvalidUserDataException import org.gradle.api.Project import org.gradle.api.file.Directory import org.gradle.api.file.DirectoryProperty @@ -272,7 +273,7 @@ internal abstract class PaperclipService : BuildService>(Constants.Services.PAPERCLIP).flatMap { it.service } private val paperclipJar: RegularFileProperty = this.project.objects.fileProperty() + /** + * Run Paper makes use of Paper's `add-plugin` command line option in order to + * load the files in [pluginJars] as plugins. This option was implemented during + * the Minecraft 1.16.5 development cycle, and does not exist in prior versions. + * + * Enabling legacy plugin loading instructs Run Paper to copy jars into the plugins + * folder instead of using the aforementioned command line option, for better + * compatibility with legacy Minecraft versions. + * + * If left un-configured, Run Paper will attempt to automatically + * determine the appropriate setting based on the configured + * Minecraft version for this task. + */ + @get:Optional + @get:Input + public abstract val legacyPluginLoading: Property + /** * The run directory for the test server. * Defaults to `run` in the project directory. @@ -61,8 +80,8 @@ public abstract class RunServerTask : JavaExec() { * Adding files to this collection may also be useful for projects which produce * more than one plugin jar, or to load dependency plugins. */ - @InputFiles - public val pluginJars: ConfigurableFileCollection = this.project.objects.fileCollection() + @get:InputFiles + public abstract val pluginJars: ConfigurableFileCollection override fun exec() { this.configure() @@ -79,13 +98,16 @@ public abstract class RunServerTask : JavaExec() { this.standardInput = System.`in` this.workingDir(this.runDirectory) - val paperclip = this.paperclipJar.orElse { + + val paperclip = if (this.paperclipJar.isPresent) { + this.paperclipJar.get().asFile + } else { this.paperclipService.get().resolvePaperclip( this.project, this.minecraftVersion.get(), this.paperBuild.get() ) - }.get().asFile + } this.classpath(paperclip) // Set disable watchdog property for debugging @@ -94,8 +116,9 @@ public abstract class RunServerTask : JavaExec() { this.systemProperty("net.kyori.adventure.text.warnWhenLegacyFormattingDetected", true) // Add our arguments - this.args("--nogui") - this.args(this.pluginJars.files.map { "-add-plugin=${it.absolutePath}" }) + if (this.minecraftVersionIsSameOrNewerThan(1, 15)) { + this.args("--nogui") + } } private fun beforeExec() { @@ -104,6 +127,56 @@ public abstract class RunServerTask : JavaExec() { if (!workingDir.exists()) { workingDir.mkdirs() } + + val plugins = workingDir.resolve("plugins") + if (!plugins.exists()) { + plugins.mkdirs() + } + + val prefix = "_run-paper_plugin_" + val extension = ".jar" + + // Delete any jars left over from previous legacy mode runs + plugins.listFiles() + ?.filter { it.isFile } + ?.filter { it.name.startsWith(prefix) && it.name.endsWith(extension) } + ?.forEach { it.delete() } + + // Add plugins + if (this.addPluginArgumentSupported()) { + this.args(this.pluginJars.files.map { "-add-plugin=${it.absolutePath}" }) + } else { + this.pluginJars.files.forEachIndexed { i, jar -> + jar.copyTo(plugins.resolve(prefix + i + extension)) + } + } + } + + private fun addPluginArgumentSupported(): Boolean { + if (this.legacyPluginLoading.isPresent) { + return !this.legacyPluginLoading.get() + } + + return this.minecraftVersionIsSameOrNewerThan(1, 16, 5) + } + + private fun minecraftVersionIsSameOrNewerThan(vararg other: Int): Boolean { + val minecraft = this.minecraftVersion.get().split(".").map { + try { + it.toInt() + } catch (ex: NumberFormatException) { + return true + } + } + + for ((current, target) in minecraft zip other.toList()) { + if (current < target) return false + if (current > target) return true + // If equal, check next subversion + } + + // version is same + return true } /** @@ -187,6 +260,13 @@ public abstract class RunServerTask : JavaExec() { this.pluginJars.from(jars) } + /** + * Convenience method setting [legacyPluginLoading] to `true`. + */ + public fun legacyPluginLoading() { + this.legacyPluginLoading.set(true) + } + /** * Represents a build of Paper. */