diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bcd4d3..c118524 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,12 +3,22 @@ ### Added - Support setting "api-version" containing a patch version for v1.20.5+ +- Add dependency substitution rules fixing paper groupId and substituting bukkit version. + In version catalogs placeholder value `{bukkit.version}` can be used, and it will be replaced with the actual version: + ```toml + [libraries] + paperApi = { module = "io.papermc.paper:paper-api", version = "{bukkit.apiVersion}" } + ``` ### Changed - **Breaking change!** Refactor development server implementation to use [jpenilla/run-task](https://github.com/jpenilla/run-task/) plugin and integrate run-paper for server execution, improving maintainability and compatibility with various server versions. + - Remove `bukkit.server.coreType` property. + Spigot is not supported anymore, PaperMC is the only supported server. + If you need to run other server cores, + please [file an issue](https://github.com/EndlessCodeGroup/BukkitGradle/issues/new). - **Breaking change!** Use [jpenilla/resource-factory](https://github.com/jpenilla/resource-factory) to generate `plugin.yml`. This change comes with some renames: @@ -17,11 +27,29 @@ - Task `:parsePluginMetaFile` -> `:parsePluginYaml` - Task `:mergePluginMeta` has been dropped. Use `:mainResourceFactory` instead - Package `ru.endlesscode.bukkitgradle.meta` -> `ru.endlesscode.bukkitgradle.plugin` -- Change API for disabling `plugin.yml` generation: +- - **Breaking change!** Change API for disabling `plugin.yml` generation: ```diff -bukkit.disableMetaGeneration() +bukkit.generatePluginYaml.set(false) ``` +- **Breaking change!** Don't add repositories implicitly. + It was impossible to opt out from automatic repositories adding. + From now, repositories should be added manually. For example: + ```kotlin + repositories { + mavenCentral() + papermc() + } + ``` +- **Breaking change!** + Don't set default `bukkit.apiVersion`. + It was implicitly set to `1.16.4` for the sake of simplicity, but in fact it was unobvious behavior. + Now, `bukkit.apiVersion` should be set explicitly: + ```kotlin + bukkit { + apiVersion = "1.20.5" + } + ``` - Set the default [JVM toolchain](https://docs.gradle.org/current/userguide/toolchains.html) version instead of setting JVM target and source compatibility to 1.8. By default, the minimal supported JVM version compatible with the specified `bukkit.server.version` is used. diff --git a/README.md b/README.md index 023cb33..455d2e3 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,14 @@ Gradle utilities to simplify Bukkit/Spigot plugins writing and debugging. - [Running Dev server](#running-dev-server) - [Dev server configuration](#dev-server-configuration) - [Migration Guide](#migration-guide) + - [Upgrade from 0.10.x](#upgrade-from-010x) - [Upgrade from 0.8.x](#upgrade-from-08x) - [License](#license) #### Features: + - Sets up compiler encoding to UTF-8 - Sets archivesBaseName to plugin name - Supports APIs: Bukkit, CraftBukkit, Spigot, Paper @@ -29,17 +31,14 @@ Gradle utilities to simplify Bukkit/Spigot plugins writing and debugging. - Allows running dev server from IDE - Runs server using [jpenilla/run-task] -#### TODO: -- Add smart dependency system - ## Installation -> [!NOTE] +> [!NOTE] > BukkitGradle requires Gradle 8.0+ to run ```kotlin plugins { - id("ru.endlesscode.bukkitgradle") version "0.10.1" + id("ru.endlesscode.bukkitgradle") version "0.10.1" } ``` @@ -50,6 +49,7 @@ plugins { Using snapshots To use snapshots, add jitpack repository to the `settings.gradle.kts` and specify version `develop-SNAPSHOT`: + ```kotlin // settings.gradle @@ -62,6 +62,7 @@ pluginManagement { rootProject.name = "" ``` + ```kotlin // build.gradle @@ -87,21 +88,26 @@ description = "My first Bukkit plugin built by Gradle" version = "0.1" bukkit { - apiVersion = "1.16.5" + // Target API version. Will be used both for plugin.yml and for dependencies + apiVersion = "1.21.5" } // Add the necessary API to the project dependencies { - compileOnly(bukkitApi()) + compileOnly(paperApi) // See the 'Dependencies' section for more info } + +repositories { + papermc() +} ``` That's it! During the plugin compilation `plugin.yml` will be generated with the following content: ```yaml -api-version: '1.16' +api-version: 1.21.5 name: MyPlugin version: '0.1' main: com.example.myplugin.MyPlugin @@ -119,10 +125,6 @@ The `plugin.yml` content can be configured using `bukkit.plugin { ... }` block. ```kotlin bukkit { - // Version of API. By default, 1.16.5 is used - apiVersion = "1.15.2" - - // Configure plugin.yml content plugin { name = "MyPlugin" description = "My amazing plugin" @@ -140,42 +142,44 @@ BukkitGradle provides shortcuts to add common repositories and dependencies: ```kotlin repositories { - spigot() + papermc() } dependencies { - compileOnly(paperApi()) + compileOnly(paperApi) } ``` #### Repositories - Name | Url -----------------|------------------------------------------------------------------- - spigot | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ - sk98q | https://maven.sk89q.com/repo/ - papermc | https://repo.papermc.io/repository/maven-public/ - dmulloy2 | https://repo.dmulloy2.net/nexus/repository/public/ - md5 | https://repo.md-5.net/content/groups/public/ - jitpack | https://jitpack.io/ - placeholderapi | https://repo.extendedclip.com/content/repositories/placeholderapi/ - aikar | https://repo.aikar.co/content/groups/aikar/ - codemc | https://repo.codemc.org/repository/maven-public/ +| Name | Url | +|------------------|--------------------------------------------------------------------| +| `spigot` | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ | +| `sk98q` | https://maven.sk89q.com/repo/ | +| `papermc` | https://repo.papermc.io/repository/maven-public/ | +| `dmulloy2` | https://repo.dmulloy2.net/nexus/repository/public/ | +| `md5` | https://repo.md-5.net/content/groups/public/ | +| `jitpack` | https://jitpack.io/ | +| `placeholderapi` | https://repo.extendedclip.com/content/repositories/placeholderapi/ | +| `aikar` | https://repo.aikar.co/content/groups/aikar/ | +| `codemc` | https://repo.codemc.org/repository/maven-public/ | #### Dependencies -Some dependencies also add a repository needed for them. +When adding dependencies, make sure you've added the corresponding repository. - Name | Signature | Adds repository --------------|----------------------------------------|----------------- - spigot | org.spigotmc:spigot:$apiVersion | mavenLocal - spigotApi | org.spigotmc:spigot-api:$apiVersion | spigot - bukkitApi | org.bukkit:bukkit:$apiVersion | spigot - paperApi | io.papermc.paper:paper-api:$apiVersion | papermc - - **Note:** `$apiVersion` - is `${version}-R0.1-SNAPSHOT` (where `$version` is `bukkit.version`) +| Name | Signature | Official repository | +|-------------|------------------------------------------|---------------------| +| `spigot` | `org.spigotmc:spigot:$apiVersion` | `mavenLocal()`* | +| `spigotApi` | `org.spigotmc:spigot-api:$apiVersion` | `spigot()` | +| `bukkitApi` | `org.bukkit:bukkit:$apiVersion` | `mavenLocal()`** | +| `paperApi` | `io.papermc.paper:paper-api:$apiVersion` | `papermc()` | -If you need more extension-functions, [file an issue][issue]. +\* Spigot is available in `mavenLocal()` only if you've built it locally using [Spigot BuildTools][buildtools]. \ +\*\* Bukkit should be built locally. However, some versions are available in `spigot()` repository. \ +\*\*\* `$apiVersion` - is `${version}-R0.1-SNAPSHOT` (where `$version` is `bukkit.apiVersion`). + +If you need more shortcuts, [file an issue][issue]. ## Running Dev server @@ -212,9 +216,9 @@ tasks.runServer { ``` > [!TIP] -> It is possible to configure server directory shared between multiple projects. +> It is possible to configure a server directory shared between multiple projects. > Set the `bukkitgradle.server.dir` property in `$HOME/.gradle/gradle.properties`. -> +> > This file contains local configurations to be used for all Gradle projects. > The value specified in project's `gradle.properties` takes precedence over the global one. @@ -227,7 +231,7 @@ bukkit { // INFO: Default values are used here server { // Server version - version = "1.16.4" // If not specified, bukkit.apiVersion will be used + version = "1.21.5" // If not specified, bukkit.apiVersion will be used // Accept EULA eula = false // Set online-mode flag @@ -253,9 +257,9 @@ bukkit { ### Upgrade from 0.10.x 1. Update Gradle to 8.0 or newer (the latest version is recommended): -```shell -./gradlew wrapper --gradle-version 8.13 -``` + ```shell + ./gradlew wrapper --gradle-version 8.13 + ``` 2. Replace deprecated and removed APIs: ```diff @@ -268,8 +272,26 @@ bukkit { } } ``` + +3. Specify `bukkit.apiVersion` explicitly. Previously it was implicitly set to `1.16.4`: + ```kotlin + bukkit { + apiVersion = "1.21.5" + } + ``` + +4. Remove server core selection: `bukkit.server.coreType` and `bukkit.server.setCore(...)`. + Paper is the only supported server core now. -3. If you have `plugin.yml`, move it's content to `bukkit.plugin { ... }` block +5. If you have `plugin.yml`, move it's content to `bukkit.plugin { ... }` block and delete the file. + +6. Explicitly add `mavenCentral()` to the repositories if you're using dependencies from it: + ```kotlin + repositories { + mavenCentral() + } + ``` + Add repositories for Bukkit/Spigot/Paper according to the [dependency table](#dependencies). ### Upgrade from 0.8.x @@ -316,7 +338,7 @@ bukkit { ``` 5. Remove `q` and `qq` functions calls in `meta { ... }` 6. Check generated plugin.yml contents after build. - + If there are any problems, [create an issue][issue]. ## License @@ -324,4 +346,5 @@ If there are any problems, [create an issue][issue]. [MIT](LICENSE) (c) 2020 EndlessCode Group [jpenilla/run-task]: https://github.com/jpenilla/run-task/ +[buildtools]: https://www.spigotmc.org/wiki/buildtools/ [issue]: https://github.com/EndlessCodeGroup/BukkitGradle/issues/new diff --git a/src/main/kotlin/BukkitExtension.kt b/src/main/kotlin/BukkitExtension.kt index 8cf2adc..676b262 100644 --- a/src/main/kotlin/BukkitExtension.kt +++ b/src/main/kotlin/BukkitExtension.kt @@ -1,28 +1,32 @@ package ru.endlesscode.bukkitgradle import org.gradle.api.Action -import org.gradle.api.Project import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Property -import org.gradle.kotlin.dsl.getByType +import org.gradle.api.provider.ProviderFactory import org.gradle.kotlin.dsl.property -import ru.endlesscode.bukkitgradle.extensions.finalizedOnRead +import ru.endlesscode.bukkitgradle.extensions.finalizeAndGet import ru.endlesscode.bukkitgradle.plugin.plugin -import ru.endlesscode.bukkitgradle.server.ServerConstants +import ru.endlesscode.bukkitgradle.plugin.util.MinecraftVersion import ru.endlesscode.bukkitgradle.server.extension.ServerConfigurationImpl import xyz.jpenilla.resourcefactory.bukkit.BukkitPluginYaml public open class BukkitExtension internal constructor( public final override val server: ServerConfigurationImpl, objects: ObjectFactory, + providers: ProviderFactory, ) : Bukkit { override val generatePluginYaml: Property = objects.property() .convention(true) public final override val apiVersion: Property = objects.property() - .convention(ServerConstants.DEFAULT_VERSION) - .finalizedOnRead() + + internal val finalApiVersion = providers.provider { + check(apiVersion.isPresent) { "Please, set 'bukkit.apiVersion' property." } + apiVersion.finalizeAndGet() + } + internal val parsedApiVersion = finalApiVersion.map(MinecraftVersion::parse) public fun server(body: Action) { body.execute(server) @@ -46,5 +50,3 @@ public open class BukkitExtension internal constructor( public const val NAME: String = "bukkit" } } - -internal val Project.bukkit: Bukkit get() = extensions.getByType() diff --git a/src/main/kotlin/BukkitGradlePlugin.kt b/src/main/kotlin/BukkitGradlePlugin.kt index 00edf50..f18ea66 100644 --- a/src/main/kotlin/BukkitGradlePlugin.kt +++ b/src/main/kotlin/BukkitGradlePlugin.kt @@ -5,29 +5,20 @@ import org.gradle.api.Project import org.gradle.api.plugins.JavaBasePlugin import org.gradle.api.plugins.JavaPlugin import org.gradle.api.tasks.compile.JavaCompile -import org.gradle.kotlin.dsl.* -import ru.endlesscode.bukkitgradle.dependencies.Dependencies +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.create +import org.gradle.kotlin.dsl.hasPlugin +import org.gradle.kotlin.dsl.withType +import ru.endlesscode.bukkitgradle.dependencies.Dependencies.configureDependencyExtensions import ru.endlesscode.bukkitgradle.extensions.java import ru.endlesscode.bukkitgradle.plugin.configurePluginYamlFeature -import ru.endlesscode.bukkitgradle.plugin.util.parsedApiVersion import ru.endlesscode.bukkitgradle.plugin.util.resolveMinimalJavaVersion -import ru.endlesscode.bukkitgradle.server.DevServerPlugin +import ru.endlesscode.bukkitgradle.server.configureDevServerFeature import ru.endlesscode.bukkitgradle.server.extension.ServerConfigurationImpl public class BukkitGradlePlugin : Plugin { - override fun apply(target: Project) { - target.configureProject() - } - - private fun Project.configureProject() { - addRepositories() - addPlugins() - configureEncoding() - Dependencies.configureProject(project) - } - - private fun Project.addPlugins() { + override fun apply(target: Project): Unit = with(target) { // Apply Java plugin, but only if another JVM-language plugin wasn't applied before if (!plugins.hasPlugin(JavaBasePlugin::class)) { plugins.apply(JavaPlugin::class) @@ -39,22 +30,19 @@ public class BukkitGradlePlugin : Plugin { ) configurePluginYamlFeature(bukkit) - apply() + configureDevServerFeature(bukkit) + + configureJavaCompilation(bukkit) + configureDependencyExtensions(bukkit) + } + private fun Project.configureJavaCompilation(bukkit: BukkitExtension) { java.toolchain { languageVersion.convention(bukkit.parsedApiVersion.map(::resolveMinimalJavaVersion)) } - } - private fun Project.configureEncoding() { tasks.withType().configureEach { options.encoding = "UTF-8" } } - - private fun Project.addRepositories() { - repositories { - mavenCentral() - } - } } diff --git a/src/main/kotlin/dependencies/Dependencies.kt b/src/main/kotlin/dependencies/Dependencies.kt index 158be73..6faf345 100644 --- a/src/main/kotlin/dependencies/Dependencies.kt +++ b/src/main/kotlin/dependencies/Dependencies.kt @@ -7,13 +7,10 @@ import org.gradle.api.artifacts.dsl.DependencyHandler import org.gradle.api.artifacts.dsl.RepositoryHandler import org.gradle.api.artifacts.repositories.MavenArtifactRepository import org.gradle.api.plugins.ExtraPropertiesExtension -import org.gradle.api.provider.Provider -import org.gradle.kotlin.dsl.KotlinClosure0 import org.gradle.kotlin.dsl.extra import org.gradle.kotlin.dsl.maven -import ru.endlesscode.bukkitgradle.bukkit +import ru.endlesscode.bukkitgradle.BukkitExtension import ru.endlesscode.bukkitgradle.plugin.util.MinecraftVersion -import ru.endlesscode.bukkitgradle.plugin.util.parsedApiVersion private typealias RepositoryClosure = Closure @@ -29,43 +26,40 @@ internal object Dependencies { const val URL_AIKAR = "https://repo.aikar.co/content/groups/aikar/" const val URL_CODEMC = "https://repo.codemc.org/repository/maven-public/" - private lateinit var apiVersion: Provider - private lateinit var parsedApiVersion: Provider + const val BUKKIT_VERSION_PLACEHOLDER = "{bukkit.apiVersion}" + const val BUKKIT_VERSION_SUFFIX = "-R0.1-SNAPSHOT" - private lateinit var repoHandler: RepositoryHandler - private lateinit var depHandler: DependencyHandler + const val PAPER_GROUP = "io.papermc.paper" + const val PAPER_OLD_GROUP = "com.destroystokyo.paper" private val RepositoryHandler.extra: ExtraPropertiesExtension get() = InvokerHelper.getProperty(this, "ext") as ExtraPropertiesExtension @JvmStatic - fun configureProject(project: Project) { - val bukkit = project.bukkit - apiVersion = bukkit.apiVersion - parsedApiVersion = bukkit.parsedApiVersion - - repoHandler = project.repositories - depHandler = project.dependencies - addGroovyExtensions() + fun Project.configureDependencyExtensions(bukkit: BukkitExtension) { + repositories.addGroovyExtensions() + dependencies.addGroovyExtensions() + + configureResolutionStrategy(bukkit) + } + + private fun RepositoryHandler.addGroovyExtensions() { + extra["spigot"] = repositoryClosure("Spigot", URL_SPIGOT) + extra["sk89q"] = repositoryClosure("sk89q", URL_SK89Q) + extra["papermc"] = repositoryClosure("PaperMC", URL_PAPERMC) + extra["dmulloy2"] = repositoryClosure("dmulloy2", URL_DMULLOY2) + extra["md5"] = repositoryClosure("md5", URL_MD5) + extra["jitpack"] = repositoryClosure("jitpack", URL_JITPACK) + extra["placeholderapi"] = repositoryClosure("PlaceholderAPI", URL_PLACEHOLDERAPI) + extra["aikar"] = repositoryClosure("aikar", URL_AIKAR) + extra["codemc"] = repositoryClosure("codemc", URL_CODEMC) } - private fun addGroovyExtensions() { - val repoExtra = repoHandler.extra - repoExtra["spigot"] = repoHandler.repositoryClosure("Spigot", URL_SPIGOT) - repoExtra["sk89q"] = repoHandler.repositoryClosure("sk89q", URL_SK89Q) - repoExtra["papermc"] = repoHandler.repositoryClosure("PaperMC", URL_PAPERMC) - repoExtra["dmulloy2"] = repoHandler.repositoryClosure("dmulloy2", URL_DMULLOY2) - repoExtra["md5"] = repoHandler.repositoryClosure("md5", URL_MD5) - repoExtra["jitpack"] = repoHandler.repositoryClosure("jitpack", URL_JITPACK) - repoExtra["placeholderapi"] = repoHandler.repositoryClosure("PlaceholderAPI", URL_PLACEHOLDERAPI) - repoExtra["aikar"] = repoHandler.repositoryClosure("aikar", URL_AIKAR) - repoExtra["codemc"] = repoHandler.repositoryClosure("codemc", URL_CODEMC) - - val depExtra = depHandler.extra - depExtra["spigot"] = depClosureOf { depHandler.api("org.spigotmc", "spigot", "mavenLocal") } - depExtra["spigotApi"] = depClosureOf { depHandler.api("org.spigotmc", "spigot-api", "spigot") } - depExtra["bukkitApi"] = depClosureOf { depHandler.api("org.bukkit", "bukkit", "spigot") } - depExtra["paperApi"] = depClosureOf { depHandler.api(resolvePaperGroupId(), "paper-api", "papermc") } + private fun DependencyHandler.addGroovyExtensions() { + extra["spigot"] = withBukkitVersion("org.spigotmc", "spigot") + extra["spigotApi"] = withBukkitVersion("org.spigotmc", "spigot-api") + extra["bukkitApi"] = withBukkitVersion("org.bukkit", "bukkit") + extra["paperApi"] = withBukkitVersion(PAPER_GROUP, "paper-api") } private fun RepositoryHandler.repositoryClosure(name: String, url: String): RepositoryClosure = @@ -85,29 +79,39 @@ internal object Dependencies { } } - @Suppress("unused") // Receiver required for scope - fun DependencyHandler.api(groupId: String, artifactId: String, vararg requiredRepos: String): String { - val version = "${apiVersion.get()}-R0.1-SNAPSHOT" - return dep(groupId, artifactId, version, *requiredRepos) + fun withBukkitVersion(groupId: String, artifactId: String): String { + return "$groupId:$artifactId:$BUKKIT_VERSION_PLACEHOLDER" } - private fun dep(groupId: String, artifactId: String, version: String, vararg requiredRepos: String): String { - for (repo in requiredRepos) { - if (repo == "mavenLocal") { - repoHandler.mavenLocal() - } else { - @Suppress("UNCHECKED_CAST") - (repoHandler.extra[repo] as RepositoryClosure).call() + private fun Project.configureResolutionStrategy(bukkit: BukkitExtension) { + val bukkitVersion = bukkit.finalApiVersion + .map { "$it$BUKKIT_VERSION_SUFFIX" } + + configurations.configureEach { + resolutionStrategy.eachDependency { + val version = if (requested.version == BUKKIT_VERSION_PLACEHOLDER) { + bukkitVersion.get() + } else { + requested.version + } + + val shouldUseOldPaperGroup by lazy { + version != null && MinecraftVersion.parse(version) < MinecraftVersion.V1_17_0 + } + val group = when (requested.group) { + PAPER_GROUP -> if (shouldUseOldPaperGroup) PAPER_OLD_GROUP else requested.group + PAPER_OLD_GROUP -> if (!shouldUseOldPaperGroup) PAPER_GROUP else requested.group + else -> requested.group + } + + if (requested.group != group) { + useTarget("$group:${requested.name}:$version") + because("Fix paper group as it was changed in 1.17") + } else if (requested.version != version && version != null) { + useVersion(version) + because("Substitute bukkit version") + } } } - - return "$groupId:$artifactId:$version" } - - internal fun resolvePaperGroupId(): String { - val useNewGroup = parsedApiVersion.get() >= MinecraftVersion.V1_17_0 - return if (useNewGroup) "io.papermc.paper" else "com.destroystokyo.paper" - } - - private fun depClosureOf(body: () -> String) = KotlinClosure0(body) } diff --git a/src/main/kotlin/dependencies/DependenciesExtensions.kt b/src/main/kotlin/dependencies/DependenciesExtensions.kt index a8d228e..3f0c410 100644 --- a/src/main/kotlin/dependencies/DependenciesExtensions.kt +++ b/src/main/kotlin/dependencies/DependenciesExtensions.kt @@ -1,10 +1,11 @@ -@file:Suppress("SpellCheckingInspection") +@file:Suppress("SpellCheckingInspection", "UnusedReceiverParameter") package ru.endlesscode.bukkitgradle.dependencies import org.gradle.api.artifacts.dsl.DependencyHandler import org.gradle.api.artifacts.dsl.RepositoryHandler import org.gradle.api.artifacts.repositories.MavenArtifactRepository +import ru.endlesscode.bukkitgradle.dependencies.Dependencies.PAPER_GROUP import ru.endlesscode.bukkitgradle.dependencies.Dependencies.URL_AIKAR import ru.endlesscode.bukkitgradle.dependencies.Dependencies.URL_CODEMC import ru.endlesscode.bukkitgradle.dependencies.Dependencies.URL_DMULLOY2 @@ -15,8 +16,7 @@ import ru.endlesscode.bukkitgradle.dependencies.Dependencies.URL_PLACEHOLDERAPI import ru.endlesscode.bukkitgradle.dependencies.Dependencies.URL_SK89Q import ru.endlesscode.bukkitgradle.dependencies.Dependencies.URL_SPIGOT import ru.endlesscode.bukkitgradle.dependencies.Dependencies.addRepo -import ru.endlesscode.bukkitgradle.dependencies.Dependencies.api -import ru.endlesscode.bukkitgradle.dependencies.Dependencies.resolvePaperGroupId +import ru.endlesscode.bukkitgradle.dependencies.Dependencies.withBukkitVersion public fun RepositoryHandler.spigot(configure: MavenArtifactRepository.() -> Unit = {}): MavenArtifactRepository = addRepo("Spigot", URL_SPIGOT, configure) @@ -46,13 +46,13 @@ public fun RepositoryHandler.codemc(configure: MavenArtifactRepository.() -> Uni addRepo("codemc", URL_CODEMC, configure) public val DependencyHandler.spigot: String - get() = api("org.spigotmc", "spigot", "mavenLocal") + get() = withBukkitVersion("org.spigotmc", "spigot") public val DependencyHandler.spigotApi: String - get() = api("org.spigotmc", "spigot-api", "spigot") + get() = withBukkitVersion("org.spigotmc", "spigot-api") public val DependencyHandler.bukkitApi: String - get() = api("org.bukkit", "bukkit", "spigot") + get() = withBukkitVersion("org.bukkit", "bukkit") public val DependencyHandler.paperApi: String - get() = api(resolvePaperGroupId(), "paper-api", "papermc") + get() = withBukkitVersion(PAPER_GROUP, "paper-api") diff --git a/src/main/kotlin/extensions/Provider.kt b/src/main/kotlin/extensions/Provider.kt index 5b6051b..005b546 100644 --- a/src/main/kotlin/extensions/Provider.kt +++ b/src/main/kotlin/extensions/Provider.kt @@ -4,8 +4,6 @@ import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import java.util.* -internal fun Property.finalizedOnRead(): Property = apply { finalizeValueOnRead() } - internal fun Property.finalizeAndGet(): T { finalizeValue() return get() diff --git a/src/main/kotlin/plugin/PluginYamlFeature.kt b/src/main/kotlin/plugin/PluginYamlFeature.kt index 6a2dc56..0caf58b 100644 --- a/src/main/kotlin/plugin/PluginYamlFeature.kt +++ b/src/main/kotlin/plugin/PluginYamlFeature.kt @@ -15,7 +15,6 @@ import ru.endlesscode.bukkitgradle.extensions.sourceSets import ru.endlesscode.bukkitgradle.plugin.task.ParsePluginYaml import ru.endlesscode.bukkitgradle.plugin.util.MinecraftVersion import ru.endlesscode.bukkitgradle.plugin.util.StringUtils -import ru.endlesscode.bukkitgradle.plugin.util.parsedApiVersion import xyz.jpenilla.resourcefactory.ExecuteResourceFactories import xyz.jpenilla.resourcefactory.ResourceFactoryPlugin import xyz.jpenilla.resourcefactory.bukkit.BukkitPluginYaml diff --git a/src/main/kotlin/plugin/util/MinecraftVersion.kt b/src/main/kotlin/plugin/util/MinecraftVersion.kt index 6623b88..412fd7a 100644 --- a/src/main/kotlin/plugin/util/MinecraftVersion.kt +++ b/src/main/kotlin/plugin/util/MinecraftVersion.kt @@ -1,7 +1,7 @@ package ru.endlesscode.bukkitgradle.plugin.util import org.gradle.jvm.toolchain.JavaLanguageVersion -import ru.endlesscode.bukkitgradle.Bukkit +import ru.endlesscode.bukkitgradle.dependencies.Dependencies @JvmInline internal value class MinecraftVersion(private val value: Int) : Comparable { @@ -16,7 +16,9 @@ internal value class MinecraftVersion(private val value: Int) : Comparable() + val configuredServerDir = resolveConfiguredServerDir() + + // Preconfigure the RunServer task + val serverConfiguration = bukkit.server + val serverVersion = provider { serverConfiguration.version }.orElse(bukkit.finalApiVersion) + val runServer = tasks.named("runServer") { + version.convention(serverVersion) + if (configuredServerDir != null) runDirectory.convention(configuredServerDir) + jvmArgs(serverConfiguration.buildJvmArgs()) + args(serverConfiguration.bukkitArgs) + + defaultCharacterEncoding = serverConfiguration.encoding + debugOptions { + enabled.convention(serverConfiguration.debug) + suspend.convention(false) + } + } + + // RunPaperPlugin uses afterEvaluate under the hood, so we have to use afterEvaluate + // to set our conventions after their ones + afterEvaluate { configureDefaultJvmForServer() } + + val prepareServer = registerPrepareServerTask(serverConfiguration, runServer) + runServer.configure { dependsOn(prepareServer) } + + registerBuildIdeRunTask(runServer) +} + +private fun Project.configureDefaultJvmForServer() { + val toolchains = project.extensions.findByType() ?: return + val spec = java.toolchain + + tasks.withType().configureEach { + javaLauncher.convention( + toolchains.launcherFor { + languageVersion.convention(version.map(::resolveMinimalJavaVersion)) + implementation.convention(spec.implementation) + vendor.convention(spec.vendor) + } + ) + } +} + +private fun Project.resolveConfiguredServerDir(): Provider? { + val deprecated = DeprecatedServerProperties(rootDir, providers) + + val serverDirProperty = providers.gradleProperty("bukkitgradle.server.dir") + .orElse(provider { deprecated.devServerDir?.absolutePath }) + .orNull ?: return null + return layout.dir(provider { file(serverDirProperty) }) +} + +private fun Project.registerPrepareServerTask( + serverConfiguration: ServerConfiguration, + runServer: Provider, +): TaskProvider { + return tasks.register("prepareServer") { + serverDir.set(runServer.map { it.runDirectory.get() }) + onlineMode = serverConfiguration.onlineMode + } +} + +private fun Project.registerBuildIdeRunTask(runServer: TaskProvider) { + tasks.register("buildIdeaRun") { + configurationName.set("Run Server [${project.name}]") + taskNames.add(runServer.name) + } +} diff --git a/src/main/kotlin/server/DevServerPlugin.kt b/src/main/kotlin/server/DevServerPlugin.kt deleted file mode 100644 index 04d9187..0000000 --- a/src/main/kotlin/server/DevServerPlugin.kt +++ /dev/null @@ -1,107 +0,0 @@ -package ru.endlesscode.bukkitgradle.server - -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.file.Directory -import org.gradle.api.provider.Provider -import org.gradle.api.tasks.TaskContainer -import org.gradle.api.tasks.TaskProvider -import org.gradle.jvm.toolchain.JavaToolchainService -import org.gradle.kotlin.dsl.* -import ru.endlesscode.bukkitgradle.Bukkit -import ru.endlesscode.bukkitgradle.bukkit -import ru.endlesscode.bukkitgradle.extensions.java -import ru.endlesscode.bukkitgradle.plugin.util.resolveMinimalJavaVersion -import ru.endlesscode.bukkitgradle.server.extension.ServerConfiguration -import ru.endlesscode.bukkitgradle.server.task.CreateIdeaGradleRunConfiguration -import ru.endlesscode.bukkitgradle.server.task.PrepareServer -import xyz.jpenilla.runpaper.RunPaperPlugin -import xyz.jpenilla.runpaper.task.RunServer -import java.io.File - -public class DevServerPlugin : Plugin { - - private lateinit var project: Project - private lateinit var bukkit: Bukkit - - private val serverConfiguration: ServerConfiguration - get() = bukkit.server - - private val tasks: TaskContainer - get() = project.tasks - - @Override - override fun apply(target: Project) { - project = target - bukkit = project.bukkit - - target.apply() - val configuredServerDir = target.resolveConfiguredServerDir() - - // Preconfigure RunServer task - val serverVersion = project.provider { serverConfiguration.version }.orElse(bukkit.apiVersion) - val runServer = tasks.named("runServer") { - version.convention(serverVersion) - if (configuredServerDir != null) runDirectory.convention(configuredServerDir) - jvmArgs(serverConfiguration.buildJvmArgs()) - args(serverConfiguration.bukkitArgs) - - defaultCharacterEncoding = serverConfiguration.encoding - debugOptions { - enabled.convention(serverConfiguration.debug) - suspend.convention(false) - } - } - - // RunPaperPlugin uses afterEvaluate under the hood, so we have to use afterEvaluate - // to set our conventions after their ones - project.afterEvaluate { configureDefaultJvmForServer() } - - val prepareServer = registerPrepareServerTask(runServer) - runServer.configure { dependsOn(prepareServer) } - - registerBuildIdeRunTask(runServer) - } - - private fun Project.configureDefaultJvmForServer() { - val toolchains = project.extensions.findByType() ?: return - val spec = java.toolchain - - tasks.withType().configureEach { - javaLauncher.convention( - toolchains.launcherFor { - languageVersion.convention(version.map(::resolveMinimalJavaVersion)) - implementation.convention(spec.implementation) - vendor.convention(spec.vendor) - } - ) - } - } - - private fun Project.resolveConfiguredServerDir(): Provider? { - val deprecated = DeprecatedServerProperties(rootDir, providers) - - val serverDirProperty = providers.gradleProperty("bukkitgradle.server.dir") - .orElse(provider { deprecated.devServerDir?.absolutePath }) - .orNull ?: return null - val serverDirFile = provider { File(serverDirProperty).absoluteFile } - return layout.dir(serverDirFile) - } - - private fun registerPrepareServerTask( - runServer: Provider, - ): TaskProvider { - return tasks.register("prepareServer") { - this.serverDir.set(runServer.map { it.runDirectory.get() }) - eula = serverConfiguration.eula - onlineMode = serverConfiguration.onlineMode - } - } - - private fun registerBuildIdeRunTask(runServer: TaskProvider) { - tasks.register("buildIdeaRun") { - configurationName.set("Run Server [${project.name}]") - taskNames.add(runServer.name) - } - } -} diff --git a/src/main/kotlin/server/extension/CoreType.kt b/src/main/kotlin/server/extension/CoreType.kt deleted file mode 100644 index 6c97f21..0000000 --- a/src/main/kotlin/server/extension/CoreType.kt +++ /dev/null @@ -1,6 +0,0 @@ -package ru.endlesscode.bukkitgradle.server.extension - -/** Supported server core types to run. */ -public enum class CoreType { - SPIGOT, PAPER -} diff --git a/src/main/kotlin/server/extension/ServerConfiguration.kt b/src/main/kotlin/server/extension/ServerConfiguration.kt index 780b928..705aa17 100644 --- a/src/main/kotlin/server/extension/ServerConfiguration.kt +++ b/src/main/kotlin/server/extension/ServerConfiguration.kt @@ -9,7 +9,6 @@ public interface ServerConfiguration { public val encoding: String public val javaArgs: List public val bukkitArgs: List - public val coreType: CoreType /** Returns arguments for JVM. */ public fun buildJvmArgs(): List diff --git a/src/main/kotlin/server/extension/ServerConfigurationImpl.kt b/src/main/kotlin/server/extension/ServerConfigurationImpl.kt index 10bcfc8..0368524 100644 --- a/src/main/kotlin/server/extension/ServerConfigurationImpl.kt +++ b/src/main/kotlin/server/extension/ServerConfigurationImpl.kt @@ -2,7 +2,6 @@ package ru.endlesscode.bukkitgradle.server.extension import org.slf4j.Logger import org.slf4j.LoggerFactory -import java.util.* public class ServerConfigurationImpl : ServerConfiguration { @@ -17,25 +16,17 @@ public class ServerConfigurationImpl : ServerConfiguration { override var javaArgs: List = listOf("-Xmx1G") override var bukkitArgs: List = emptyList() - override var coreType: CoreType = CoreType.SPIGOT - - /** - * Sets core from string. - * @see coreType - */ + @Suppress("UNUSED_PARAMETER") + @Deprecated("Core selecting is not supported anymore. Paper is always used.") public fun setCore(core: String) { - try { - coreType = CoreType.valueOf(core.uppercase(Locale.ENGLISH)) - } catch (_: IllegalArgumentException) { - logger.warn( - """ - Core type '$core' not found. May be it doesn't supported by BukkitGradle yet. - Fallback core type is '${coreType.name}'. - Supported types: ${CoreType.values().joinToString(", ")} - Write an issue on GitHub to request support of other cores. - """.trimIndent() - ) - } + logger.warn( + """ + Server core selecting is not supported anymore. Paper is always used. + Please, remove `bukkit.server.setCore(...)` from your build script. + If you want to use other server core, file an issue: + https://github.com/EndlessCodeGroup/BukkitGradle/issues/new + """.trimIndent() + ) } /** Append the given [args] to `javaArgs`. */ @@ -62,7 +53,6 @@ public class ServerConfigurationImpl : ServerConfiguration { ", encoding='$encoding'" + ", javaArgs='$javaArgs'" + ", bukkitArgs='$bukkitArgs'" + - ", coreType=$coreType" + "}" } diff --git a/src/main/kotlin/server/task/PrepareServer.kt b/src/main/kotlin/server/task/PrepareServer.kt index d9383d1..2a1aec9 100644 --- a/src/main/kotlin/server/task/PrepareServer.kt +++ b/src/main/kotlin/server/task/PrepareServer.kt @@ -16,9 +16,6 @@ internal abstract class PrepareServer : DefaultTask() { @get:Internal abstract val serverDir: DirectoryProperty - @get:Input - var eula: Boolean = false - @get:Input var onlineMode: Boolean = true @@ -32,18 +29,18 @@ internal abstract class PrepareServer : DefaultTask() { @TaskAction fun prepareServer() { - resolveOnlineMode() + configureOnlineMode() } - private fun resolveOnlineMode() { + private fun configureOnlineMode() { val propsFile = propertiesFile.get().asFile if (!propsFile.exists()) { propsFile.createNewFile() } val properties = Properties() - properties.load(propsFile.reader()) + propsFile.reader().use { properties.load(it) } properties.setProperty("online-mode", "$onlineMode") - properties.store(propsFile.writer(), "Minecraft server properties") + propsFile.writer().use { properties.store(it, "Minecraft server properties") } } } diff --git a/src/test/groovy/ru/endlesscode/bukkitgradle/BukkitGradlePluginSpec.groovy b/src/test/groovy/ru/endlesscode/bukkitgradle/BukkitGradlePluginSpec.groovy index 7d46aa3..c1838a9 100644 --- a/src/test/groovy/ru/endlesscode/bukkitgradle/BukkitGradlePluginSpec.groovy +++ b/src/test/groovy/ru/endlesscode/bukkitgradle/BukkitGradlePluginSpec.groovy @@ -7,11 +7,20 @@ class BukkitGradlePluginSpec extends PluginSpecification { project.apply(plugin: BukkitGradlePlugin) } + def "when initialized - and apiVersion is not set - should show an error"() { + when: "use some API requiring apiVersion to be set" + project.java.toolchain.languageVersion.get() + + then: + def exception = thrown(RuntimeException) + exception.cause.message == "Please, set 'bukkit.apiVersion' property." + } + def "when initialized - should set default JVM toolchain"(String apiVersion, int jvmVersion) { - when: "apiVersion is set" + given: "apiVersion is set" project.bukkit.apiVersion = apiVersion - then: "JVM toolchain version should be" + expect: "JVM toolchain version should be" project.java.toolchain.languageVersion.get().asInt() == jvmVersion where: @@ -32,57 +41,73 @@ class BukkitGradlePluginSpec extends PluginSpecification { project.repositories.findByName("sk89q") != null } - def "when use bukkit extension - and bukkit version not set - should return bukkit dependency with default version"() { - when: "use bukkit extension" - String dependency = project.dependencies.bukkitApi() + def "when use bukkit extension - should return bukkit dependency with version placeholder"() { + when: + String dependency = project.dependencies.bukkitApi - then: "returned bukkit dependency with default version" - dependency == 'org.bukkit:bukkit:1.16.4-R0.1-SNAPSHOT' + then: + dependency == 'org.bukkit:bukkit:{bukkit.apiVersion}' } def "when using paper extension - should add paper dependency"(String apiVersion, String groupId) { - when: "apiVersion is set" + given: project.bukkit.apiVersion = apiVersion - and: "use paperApi extension" - String dependency = project.dependencies.paperApi() + when: "use paperApi extension" + project.dependencies { + compileOnly(paperApi) { transitive = false } + } - then: "returns paper dependency with right groupId" - dependency == "$groupId:paper-api:$apiVersion-R0.1-SNAPSHOT" + project.repositories { + papermc() + } + + then: "resolved paper dependency with correct groupId" + resolvedDependency().startsWith("$groupId:paper-api:$apiVersion-R0.1-SNAPSHOT") where: apiVersion | groupId "1.16.5" | "com.destroystokyo.paper" - "1.17" | "io.papermc.paper" + "1.18" | "io.papermc.paper" } - def "when use bukkit extension - and bukkit version set - should return bukkit with specified version"() { - given: "api version specified" - project.bukkit.apiVersion = "1.7.10" + def "when using paper with old group and new version - should fix the group"() { + given: + project.bukkit.apiVersion = "1.18" - when: "use bukkit extension" - String dependency = project.dependencies.bukkitApi() + when: + project.dependencies { + compileOnly("com.destroystokyo.paper:paper-api:1.17-R0.1-SNAPSHOT") + } + + project.repositories { + papermc() + } - then: "returned bukkit dependency with the specified version" - dependency == 'org.bukkit:bukkit:1.7.10-R0.1-SNAPSHOT' + then: "resolved paper dependency with correct groupId" + resolvedDependency().startsWith("io.papermc.paper:paper-api:1.17-R0.1-SNAPSHOT") } - def "when use bukkit extension - should add required repo"() { - when: "use bukkit dependency" - project.dependencies.bukkitApi() + def "when use bukkit extension - and bukkit version set - should return bukkit with specified version"() { + given: "api version specified" + project.bukkit.apiVersion = "1.20.5" - then: "required repository is applied" - project.repositories.findByName("Spigot") != null - } + when: "use bukkit extension" + project.dependencies { + compileOnly(spigotApi) { transitive = false } + } - def "when use spigot extension - should add repo mavenLocal"() { - given: "mavenLocal is not applied" - project.repositories.findByName("MavenLocal") == null + project.repositories { + spigot() + } - when: "use spigot extension" - project.dependencies.spigot() + then: "resolved bukkit dependency with the specified version" + resolvedDependency().startsWith('org.spigotmc:spigot-api:1.20.5-R0.1-SNAPSHOT') + } - then: "mavenLocal applied" - project.repositories.findByName("MavenLocal") != null + private String resolvedDependency() { + def compileClasspath = project.configurations.getByName("compileClasspath") + def artifacts = compileClasspath.incoming.artifacts.resolvedArtifacts.get() + return artifacts.first().id.componentIdentifier.displayName } } diff --git a/src/test/groovy/ru/endlesscode/bukkitgradle/server/extension/ServerConfigurationSpec.groovy b/src/test/groovy/ru/endlesscode/bukkitgradle/server/extension/ServerConfigurationSpec.groovy index ad49717..350fce6 100644 --- a/src/test/groovy/ru/endlesscode/bukkitgradle/server/extension/ServerConfigurationSpec.groovy +++ b/src/test/groovy/ru/endlesscode/bukkitgradle/server/extension/ServerConfigurationSpec.groovy @@ -19,28 +19,4 @@ class ServerConfigurationSpec extends Specification { then: ["-Dcom.mojang.eula.agree=true", "-Xmx1G"] == args } - - void 'when set existing core - should set core successfully'() { - when: - serverConfiguration.core = "paper" - - then: - CoreType.PAPER == serverConfiguration.coreType - } - - void 'when set existing core in mixed case - should set core successfully'() { - when: - serverConfiguration.core = "Paper" - - then: - CoreType.PAPER == serverConfiguration.coreType - } - - void 'when set not existing core - should fallback to spigot core'() { - when: - serverConfiguration.core = "uber-bukkit" - - then: - CoreType.SPIGOT == serverConfiguration.coreType - } }