diff --git a/.gitignore b/.gitignore index af8e2f8..5557e5e 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,6 @@ build/ # IntelliJ out/ + +# Kotlin +.kotlin/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 304f17a..a3f3920 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,26 @@ ## [Unreleased] -*No changes yet* +### Features + +- Support Paper 26.1+ + - `paperApi` resolves the latest Paper build for `bukkit.apiVersion`, e.g. `26.1.2` -> `26.1.2.build.74-stable` + - Use Java 25 by default for 26.1+ +- Update [jpenilla/run-task](https://github.com/jpenilla/run-task/) to 3.1.0. + It downloads Paper using the new Fill v3 API, so 26.x servers can be downloaded. + +### Fixed + +- Run dev server with at least the Java version used to build the plugin. + Previously, a plugin compiled with a newer Java than the server's minimal one failed to load. +- Don't modify `plugin.yml` and other files in `src/main/resources`. + Previously, if `plugin.yml` existed in resources, it was overwritten by the generated one, and other resources were deleted. + Now `plugin.yml` from resources is used only as defaults for the generated `plugin.yml`. +- Update the generated `plugin.yml` when the build configuration changes. + Previously, values from the earlier generated `plugin.yml` took precedence. + +### Housekeeping + +- **Breaking change!** BukkitGradle requires Gradle 9.7+ now ## [1.0.0] - 2025-04-18 diff --git a/README.md b/README.md index a9837af..a6883b7 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Gradle utilities to simplify Bukkit/Spigot plugins writing and debugging. ## Installation > [!NOTE] -> BukkitGradle requires Gradle 8.0+ to run +> BukkitGradle requires Gradle 9.7+ to run ```kotlin plugins { @@ -101,6 +101,10 @@ repositories { } ``` +> [!NOTE] +> `bukkit.apiVersion` should be a version published by Paper, for example `1.21`, `1.21.11` or `26.1.2`. +> Paper skipped 26.1 and 26.1.1 has only alpha builds, so use `26.1.2` to target 26.1. + That's it! During the plugin compilation `plugin.yml` will be generated with the following content: @@ -175,7 +179,8 @@ When adding dependencies, make sure you've added the corresponding repository. \* 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`). +\*\*\* `$apiVersion` - is `${version}-R0.1-SNAPSHOT` (where `$version` is `bukkit.apiVersion`). \ +Since 26.1, `paperApi` uses `${version}.+` instead to pick the latest Paper build, e.g. `26.1.2` -> `26.1.2.build.74-stable`. If you need more shortcuts, [file an issue][issue]. @@ -254,9 +259,9 @@ bukkit { ### Upgrade from 0.10.x -1. Update Gradle to 8.0 or newer (the latest version is recommended): +1. Update Gradle to 9.7 or newer (the latest version is recommended): ```shell - ./gradlew wrapper --gradle-version 8.13 + ./gradlew wrapper --gradle-version latest ``` 2. Replace deprecated and removed APIs: diff --git a/build.gradle.kts b/build.gradle.kts index 5a617ab..3dda12e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -28,14 +28,15 @@ repositories { } dependencies { - implementation("xyz.jpenilla.run-paper:xyz.jpenilla.run-paper.gradle.plugin:2.3.1") + implementation("xyz.jpenilla.run-paper:xyz.jpenilla.run-paper.gradle.plugin:3.1.0") implementation("xyz.jpenilla.resource-factory:xyz.jpenilla.resource-factory.gradle.plugin:1.2.0") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.1") implementation("com.charleskorn.kaml:kaml:0.74.0") testImplementation("junit:junit:4.13.1") - testImplementation(platform("org.spockframework:spock-bom:2.3-groovy-3.0")) + testImplementation(platform("org.spockframework:spock-bom:2.3-groovy-4.0")) testImplementation("org.spockframework:spock-core") testImplementation("org.spockframework:spock-junit4") + testRuntimeOnly("org.junit.platform:junit-platform-launcher") } val runningOnCi = System.getenv("CI") == "true" diff --git a/gradle.properties b/gradle.properties index b9a2729..89f20f6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ group=ru.endlesscode description=Simple development of Bukkit plugins with Gradle -version=1.0.1-SNAPSHOT +version=1.1.0-SNAPSHOT org.gradle.jvmargs=-Xmx3G org.gradle.parallel=true org.gradle.daemon=true diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 9bbc975..9fa7f28 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 37f853b..91c4fc6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,9 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.2-bin.zip networkTimeout=10000 +retries=0 +retryBackOffMs=500 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index faf9300..249efbb 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ ############################################################################## # -# Gradle start up script for POSIX generated by Gradle. +# gradlew start up script for POSIX generated by Gradle. # # Important for running: # @@ -29,7 +29,7 @@ # bash, then to run this script, type that shell name before the whole # command line, like: # -# ksh Gradle +# ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -114,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -172,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -212,8 +210,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9d21a21..3185a43 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -19,12 +19,39 @@ @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions + +@rem Catch executions from older scripts and ensure they exit cleanly. +@rem This can be removed once we can be reasonably confident that few people +@rem will be migrating directly to this new wrapper. +goto afterSafetyNet +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +goto exitWithErrorLevel +:afterSafetyNet set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @@ -45,13 +72,14 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 +1>&2 echo. +1>&2 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +1>&2 echo. +1>&2 echo Please set the JAVA_HOME variable in your environment to match the +1>&2 echo location of your Java installation. -goto fail +"%COMSPEC%" /c exit 1 +goto exitWithErrorLevel :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -59,36 +87,26 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 +1>&2 echo. +1>&2 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +1>&2 echo. +1>&2 echo Please set the JAVA_HOME variable in your environment to match the +1>&2 echo location of your Java installation. -goto fail +"%COMSPEC%" /c exit 1 +goto exitWithErrorLevel :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +@rem Execute gradlew +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel & goto exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem This label must not be changed. We rely on old scripts being able to jump to this point. +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/src/main/kotlin/dependencies/Dependencies.kt b/src/main/kotlin/dependencies/Dependencies.kt index 6faf345..aae0201 100644 --- a/src/main/kotlin/dependencies/Dependencies.kt +++ b/src/main/kotlin/dependencies/Dependencies.kt @@ -84,13 +84,12 @@ internal object Dependencies { } private fun Project.configureResolutionStrategy(bukkit: BukkitExtension) { - val bukkitVersion = bukkit.finalApiVersion - .map { "$it$BUKKIT_VERSION_SUFFIX" } + val apiVersion = bukkit.finalApiVersion configurations.configureEach { resolutionStrategy.eachDependency { val version = if (requested.version == BUKKIT_VERSION_PLACEHOLDER) { - bukkitVersion.get() + resolveBukkitVersion(requested.group, apiVersion.get()) } else { requested.version } @@ -114,4 +113,11 @@ internal object Dependencies { } } } + + private fun resolveBukkitVersion(group: String, apiVersion: String): String { + // Since 26.1, paper-api is published as '.build.-', e.g. '26.1.2.build.74-stable'. + // Prefix match picks the latest build. Without a patch, it picks the latest patch: '26.1' -> '26.1.2.build.74-stable' + val usesPaperVersioning = group == PAPER_GROUP && MinecraftVersion.parse(apiVersion) >= MinecraftVersion.V26_1_0 + return if (usesPaperVersioning) "$apiVersion.+" else "$apiVersion$BUKKIT_VERSION_SUFFIX" + } } diff --git a/src/main/kotlin/extensions/Provider.kt b/src/main/kotlin/extensions/Provider.kt index 005b546..30e623b 100644 --- a/src/main/kotlin/extensions/Provider.kt +++ b/src/main/kotlin/extensions/Provider.kt @@ -4,7 +4,7 @@ import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import java.util.* -internal fun Property.finalizeAndGet(): T { +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 0caf58b..cd4d765 100644 --- a/src/main/kotlin/plugin/PluginYamlFeature.kt +++ b/src/main/kotlin/plugin/PluginYamlFeature.kt @@ -32,13 +32,24 @@ internal fun Project.configurePluginYamlFeature(bukkit: BukkitExtension) { } (bukkit as ExtensionAware).extensions.add(PLUGIN_EXTENSION_NAME, bukkitPluginYaml) - val mainSourceSet = sourceSets.named(SOURCE_SET_NAME) { + val mainSourceSet = sourceSets.named(SOURCE_SET_NAME) + val sourcePluginYaml = findPluginYaml(mainSourceSet) + mainSourceSet.configure { resourceFactory.factory(bukkitPluginYaml.resourceFactory()) + + // Package only one plugin.yml: the generated one, or the source one if the generation is disabled. + // The generated plugin.yml may be left from previous builds even if the generation is disabled. + val sourcePluginYamlFile by lazy { sourcePluginYaml.orNull?.asFile } + resources.exclude { element -> + if (element.path != PLUGIN_YML) return@exclude false + val isSource = element.file == sourcePluginYamlFile + if (bukkit.generatePluginYaml.get()) isSource else !isSource + } } val parsePluginYamlProvider = tasks.register("parsePluginYaml") { pluginYaml.set(bukkitPluginYaml) - pluginYamlFile.set(findPluginYaml(mainSourceSet)) + pluginYamlFile.set(sourcePluginYaml) onlyIf { bukkit.generatePluginYaml.finalizeAndGet() } } @@ -49,24 +60,16 @@ internal fun Project.configurePluginYamlFeature(bukkit: BukkitExtension) { if (!generatePluginYaml) return@named val parsePluginYaml = parsePluginYamlProvider.get() - - // Switch to in-place generation mode if the plugin.yml exists - if (parsePluginYaml.pluginYamlFile.isPresent) { - dependsOn(parsePluginYaml) - - val pluginYamlFile = parsePluginYaml.pluginYamlFile.get().asFile - outputDir.set(pluginYamlFile.parentFile) - // Deduplicate resource dirs after changing outputDir - mainSourceSet.configure { - resources.setSrcDirs(resources.srcDirs.distinct()) - } - } + if (parsePluginYaml.pluginYamlFile.isPresent) dependsOn(parsePluginYaml) } } private fun Project.findPluginYaml(sourceSetProvider: Provider): Provider { + val buildDirectory = layout.buildDirectory val fileProvider = sourceSetProvider.mapNotNull { sourceSet -> sourceSet.resources.sourceDirectories + // Skip generated resources, otherwise the previously generated plugin.yml would be used as defaults + .filterNot { it.startsWith(buildDirectory.get().asFile) } .map { it.resolve(PLUGIN_YML) } .find { it.isFile } } diff --git a/src/main/kotlin/plugin/task/ParsePluginYaml.kt b/src/main/kotlin/plugin/task/ParsePluginYaml.kt index a61aaa9..3231f88 100644 --- a/src/main/kotlin/plugin/task/ParsePluginYaml.kt +++ b/src/main/kotlin/plugin/task/ParsePluginYaml.kt @@ -6,11 +6,13 @@ import org.gradle.api.GradleException import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.Property import org.gradle.api.tasks.* +import org.gradle.work.DisableCachingByDefault import ru.endlesscode.bukkitgradle.TASKS_GROUP_BUKKIT import ru.endlesscode.bukkitgradle.plugin.BukkitPluginYamlDefaults import xyz.jpenilla.resourcefactory.bukkit.BukkitPluginYaml import xyz.jpenilla.resourcefactory.bukkit.Permission +@DisableCachingByDefault(because = "Parsing a small file is faster than caching") internal abstract class ParsePluginYaml : DefaultTask() { private val yaml by lazy { diff --git a/src/main/kotlin/plugin/util/MinecraftVersion.kt b/src/main/kotlin/plugin/util/MinecraftVersion.kt index 412fd7a..affeb75 100644 --- a/src/main/kotlin/plugin/util/MinecraftVersion.kt +++ b/src/main/kotlin/plugin/util/MinecraftVersion.kt @@ -1,7 +1,6 @@ package ru.endlesscode.bukkitgradle.plugin.util import org.gradle.jvm.toolchain.JavaLanguageVersion -import ru.endlesscode.bukkitgradle.dependencies.Dependencies @JvmInline internal value class MinecraftVersion(private val value: Int) : Comparable { @@ -15,25 +14,28 @@ internal value class MinecraftVersion(private val value: Int) : Comparable= MinecraftVersion.V26_1_0 -> JavaLanguageVersion.of(25) // https://minecraft.wiki/w/Java_Edition_1.20.5#General_2 version >= MinecraftVersion.V1_20_5 -> JavaLanguageVersion.of(21) // https://minecraft.wiki/w/Java_Edition_1.18#General_2 diff --git a/src/main/kotlin/server/DevServerFeature.kt b/src/main/kotlin/server/DevServerFeature.kt index 7dec434..374dc39 100644 --- a/src/main/kotlin/server/DevServerFeature.kt +++ b/src/main/kotlin/server/DevServerFeature.kt @@ -52,7 +52,9 @@ private fun Project.configureDefaultJvmForServer() { tasks.withType().configureEach { javaLauncher.convention( toolchains.launcherFor { - languageVersion.convention(version.map(::resolveMinimalJavaVersion)) + languageVersion.convention(version.map { + resolveMinimalJavaVersion(it).coerceAtLeast(spec.languageVersion.get()) + }) implementation.convention(spec.implementation) vendor.convention(spec.vendor) } diff --git a/src/main/kotlin/server/task/CreateIdeaGradleRunConfiguration.kt b/src/main/kotlin/server/task/CreateIdeaGradleRunConfiguration.kt index 4b9befe..e64d9e0 100644 --- a/src/main/kotlin/server/task/CreateIdeaGradleRunConfiguration.kt +++ b/src/main/kotlin/server/task/CreateIdeaGradleRunConfiguration.kt @@ -14,11 +14,13 @@ import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.TaskAction import org.gradle.kotlin.dsl.newInstance import org.gradle.kotlin.dsl.withGroovyBuilder +import org.gradle.work.DisableCachingByDefault import ru.endlesscode.bukkitgradle.TASKS_GROUP_BUKKIT import ru.endlesscode.bukkitgradle.server.util.Idea import javax.inject.Inject /** Builds run configuration in IDEA .xml format and stores it to a file. */ +@DisableCachingByDefault(because = "Writes a small file to the local IDE configuration") @Suppress("LeakingThis") public abstract class CreateIdeaGradleRunConfiguration private constructor( idea: Idea, diff --git a/src/main/kotlin/server/task/PrepareServer.kt b/src/main/kotlin/server/task/PrepareServer.kt index 2a1aec9..e3ca3d5 100644 --- a/src/main/kotlin/server/task/PrepareServer.kt +++ b/src/main/kotlin/server/task/PrepareServer.kt @@ -8,9 +8,11 @@ import org.gradle.api.tasks.Input import org.gradle.api.tasks.Internal import org.gradle.api.tasks.OutputFile import org.gradle.api.tasks.TaskAction +import org.gradle.work.DisableCachingByDefault import ru.endlesscode.bukkitgradle.TASKS_GROUP_BUKKIT import java.util.* +@DisableCachingByDefault(because = "Writes files to the local server directory") internal abstract class PrepareServer : DefaultTask() { @get:Internal diff --git a/src/test/groovy/ru/endlesscode/bukkitgradle/BukkitGradlePluginSpec.groovy b/src/test/groovy/ru/endlesscode/bukkitgradle/BukkitGradlePluginSpec.groovy index c1838a9..79543a3 100644 --- a/src/test/groovy/ru/endlesscode/bukkitgradle/BukkitGradlePluginSpec.groovy +++ b/src/test/groovy/ru/endlesscode/bukkitgradle/BukkitGradlePluginSpec.groovy @@ -31,6 +31,9 @@ class BukkitGradlePluginSpec extends PluginSpecification { "1.18" | 17 "1.20.4" | 17 "1.20.5" | 21 + "26.1" | 25 + "26.1.2" | 25 + "26.3" | 25 } def "when use custom repos extension - should add repos"() { @@ -49,7 +52,7 @@ class BukkitGradlePluginSpec extends PluginSpecification { dependency == 'org.bukkit:bukkit:{bukkit.apiVersion}' } - def "when using paper extension - should add paper dependency"(String apiVersion, String groupId) { + def "when using paper extension - should add paper dependency"(String apiVersion, String expectedDependency) { given: project.bukkit.apiVersion = apiVersion @@ -63,12 +66,33 @@ class BukkitGradlePluginSpec extends PluginSpecification { } then: "resolved paper dependency with correct groupId" - resolvedDependency().startsWith("$groupId:paper-api:$apiVersion-R0.1-SNAPSHOT") + resolvedDependency().startsWith(expectedDependency) where: - apiVersion | groupId - "1.16.5" | "com.destroystokyo.paper" - "1.18" | "io.papermc.paper" + apiVersion | expectedDependency + "1.16.5" | "com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT" + "1.18" | "io.papermc.paper:paper-api:1.18-R0.1-SNAPSHOT" + "1.21.11" | "io.papermc.paper:paper-api:1.21.11-R0.1-SNAPSHOT" + "26.1" | "io.papermc.paper:paper-api:26.1." + "26.1.2" | "io.papermc.paper:paper-api:26.1.2.build." + "26.3" | "io.papermc.paper:paper-api:26.3.build." + } + + def "when using paper with non-release version - should keep the version"() { + given: + project.bukkit.apiVersion = "26.3" + + when: + project.dependencies { + compileOnly("io.papermc.paper:paper-api:26.3-pre-2.build.0-alpha") { transitive = false } + } + + project.repositories { + papermc() + } + + then: + resolvedDependency() == "io.papermc.paper:paper-api:26.3-pre-2.build.0-alpha" } def "when using paper with old group and new version - should fix the group"() { @@ -88,9 +112,9 @@ class BukkitGradlePluginSpec extends PluginSpecification { resolvedDependency().startsWith("io.papermc.paper:paper-api:1.17-R0.1-SNAPSHOT") } - def "when use bukkit extension - and bukkit version set - should return bukkit with specified version"() { + def "when use bukkit extension - and bukkit version set - should return bukkit with specified version"(String apiVersion) { given: "api version specified" - project.bukkit.apiVersion = "1.20.5" + project.bukkit.apiVersion = apiVersion when: "use bukkit extension" project.dependencies { @@ -102,7 +126,10 @@ class BukkitGradlePluginSpec extends PluginSpecification { } then: "resolved bukkit dependency with the specified version" - resolvedDependency().startsWith('org.spigotmc:spigot-api:1.20.5-R0.1-SNAPSHOT') + resolvedDependency().startsWith("org.spigotmc:spigot-api:$apiVersion-R0.1-SNAPSHOT") + + where: + apiVersion << ["1.20.5", "26.1"] } private String resolvedDependency() { diff --git a/src/test/groovy/ru/endlesscode/bukkitgradle/PluginSpecification.groovy b/src/test/groovy/ru/endlesscode/bukkitgradle/PluginSpecification.groovy index 963e36e..a8c626f 100644 --- a/src/test/groovy/ru/endlesscode/bukkitgradle/PluginSpecification.groovy +++ b/src/test/groovy/ru/endlesscode/bukkitgradle/PluginSpecification.groovy @@ -58,6 +58,11 @@ class PluginSpecification extends Specification { return file } + /** Returns a file in the project directory without creating it. */ + File projectPath(String path) { + return new File(testProjectDir.root, path) + } + Project getProject() { if (project == null) { project = ProjectBuilder.builder() diff --git a/src/test/groovy/ru/endlesscode/bukkitgradle/plugin/task/GeneratePluginYamlSpec.groovy b/src/test/groovy/ru/endlesscode/bukkitgradle/plugin/task/GeneratePluginYamlSpec.groovy index 1975050..75ac8d0 100644 --- a/src/test/groovy/ru/endlesscode/bukkitgradle/plugin/task/GeneratePluginYamlSpec.groovy +++ b/src/test/groovy/ru/endlesscode/bukkitgradle/plugin/task/GeneratePluginYamlSpec.groovy @@ -12,9 +12,11 @@ class GeneratePluginYamlSpec extends PluginSpecification { private final static PARSE_PLUGIN_YAML = ':parsePluginYaml' private File pluginYamlFile + private File generatedPluginYamlFile def setup() { pluginYamlFile = file("src/main/resources/$PluginYamlFeatureKt.PLUGIN_YML") + generatedPluginYamlFile = projectPath("build/generated/resourceFactory/main/$PluginYamlFeatureKt.PLUGIN_YML") buildFile << """ bukkit.apiVersion = "1.16.2" @@ -46,6 +48,22 @@ class GeneratePluginYamlSpec extends PluginSpecification { taskOutcome(PARSE_PLUGIN_YAML) == null } + def 'when run processResources - and plugin.yml generation disabled - should use source plugin.yml'() { + given: "plugin.yml generated by a previous build" + run(':processResources') + + and: + def sourceContent = "name: SourcePlugin\n" + pluginYamlFile.text = sourceContent + buildFile << "bukkit.generatePluginYaml = false" + + when: + run(':processResources') + + then: + projectPath("build/resources/main/$PluginYamlFeatureKt.PLUGIN_YML").text == sourceContent + } + def 'when run processResources - and plugin.yml doesnt exist - should skip parsing'() { given: pluginYamlFile.delete() @@ -76,7 +94,7 @@ class GeneratePluginYamlSpec extends PluginSpecification { run(RESOURCE_FACTORY) then: "plugin file content corresponds to default config" - pluginYamlFile.text == """\ + generatedPluginYamlFile.text == """\ api-version: '1.16' name: test-plugin version: '1.0' @@ -94,7 +112,7 @@ class GeneratePluginYamlSpec extends PluginSpecification { run(RESOURCE_FACTORY) then: "plugin file content corresponds to default config" - pluginYamlFile.text == """\ + generatedPluginYamlFile.text == """\ api-version: $expectedResult name: test-plugin version: '1.0' @@ -107,6 +125,8 @@ class GeneratePluginYamlSpec extends PluginSpecification { "1.20.4" | "'1.20'" "1.20.5" | "1.20.5" "1.21.1" | "1.21.1" + "26.1" | "'26.1'" + "26.1.2" | "26.1.2" } def 'when generate plugin.yml - and generate it again - should skip second task run'() { @@ -137,7 +157,7 @@ class GeneratePluginYamlSpec extends PluginSpecification { taskOutcome(RESOURCE_FACTORY) == TaskOutcome.SUCCESS and: "plugin generated with new description" - pluginYamlFile.text == """\ + generatedPluginYamlFile.text == """\ api-version: '1.16' name: test-plugin version: '1.0' @@ -146,6 +166,45 @@ class GeneratePluginYamlSpec extends PluginSpecification { """.stripIndent() } + void 'when generate plugin.yml - and changed api version - should update plugin.yml'(boolean hasSourceFile) { + given: + if (!hasSourceFile) pluginYamlFile.delete() + + when: + run(RESOURCE_FACTORY) + + and: "changed api version" + buildFile << 'bukkit.apiVersion = "1.20.4"' + + and: + run(RESOURCE_FACTORY) + + then: + generatedPluginYamlFile.readLines().first() == "api-version: '1.20'" + + where: + hasSourceFile << [true, false] + } + + void 'when generate plugin.yml - should keep source resources unchanged'() { + given: + def sourceContent = "depend: [Vault]\n" + pluginYamlFile.text = sourceContent + def configFile = file("src/main/resources/config.yml") + configFile.text = "key: value\n" + + when: + run(':processResources') + + then: "source files are not modified" + pluginYamlFile.text == sourceContent + configFile.text == "key: value\n" + + and: "the generated plugin.yml is packaged" + projectPath("build/resources/main/$PluginYamlFeatureKt.PLUGIN_YML").text == generatedPluginYamlFile.text + projectPath("build/resources/main/config.yml").isFile() + } + void 'when generate plugin.yml - and properties configured using set'() { given: //language=kotlin @@ -167,7 +226,7 @@ class GeneratePluginYamlSpec extends PluginSpecification { run(RESOURCE_FACTORY) then: - pluginYamlFile.text == """\ + generatedPluginYamlFile.text == """\ api-version: '1.13' name: TestPlugin version: '0.1' @@ -201,7 +260,7 @@ class GeneratePluginYamlSpec extends PluginSpecification { run(RESOURCE_FACTORY) then: - pluginYamlFile.text == """\ + generatedPluginYamlFile.text == """\ api-version: '1.13' name: TestPlugin version: '0.1' @@ -231,7 +290,7 @@ class GeneratePluginYamlSpec extends PluginSpecification { run(RESOURCE_FACTORY) then: - pluginYamlFile.text == """\ + generatedPluginYamlFile.text == """\ api-version: '1.16' name: test-plugin version: '1.0' @@ -269,7 +328,7 @@ class GeneratePluginYamlSpec extends PluginSpecification { } then: - pluginYamlFile.text == """\ + generatedPluginYamlFile.text == """\ api-version: '1.16' name: test-plugin version: '1.0' @@ -291,7 +350,7 @@ class GeneratePluginYamlSpec extends PluginSpecification { run(RESOURCE_FACTORY) then: "should write plugin and keep values of the source file" - pluginYamlFile.text == """\ + generatedPluginYamlFile.text == """\ api-version: '1.16' name: SourceValue version: '1.2' @@ -336,7 +395,7 @@ class GeneratePluginYamlSpec extends PluginSpecification { run(RESOURCE_FACTORY) then: "should overwrite source fields" - pluginYamlFile.text == """\ + generatedPluginYamlFile.text == """\ api-version: '1.16' name: BuildscriptValue version: '1.3' @@ -410,6 +469,6 @@ class GeneratePluginYamlSpec extends PluginSpecification { run(RESOURCE_FACTORY) then: "the file content should remain the same" - pluginYamlFile.text == content + generatedPluginYamlFile.text == content } } diff --git a/src/test/groovy/ru/endlesscode/bukkitgradle/server/task/RunServerSpec.groovy b/src/test/groovy/ru/endlesscode/bukkitgradle/server/task/RunServerSpec.groovy index 2d5dbd7..445a8d4 100644 --- a/src/test/groovy/ru/endlesscode/bukkitgradle/server/task/RunServerSpec.groovy +++ b/src/test/groovy/ru/endlesscode/bukkitgradle/server/task/RunServerSpec.groovy @@ -15,4 +15,25 @@ class RunServerSpec extends PluginSpecification { expect: "runServer depends on prepareServer" task.dependsOn.collect { it.name } == ["prepareServer"] } + + def "when toolchain is newer than server minimal Java - should run server with toolchain Java"() { + given: "server requires Java 8, but plugin is compiled with Java 17" + //language=kotlin + buildFile << """ + bukkit.apiVersion = "1.16.5" + java.toolchain.languageVersion = JavaLanguageVersion.of(17) + + tasks.register("printServerJava") { + val launcher = tasks.named("$TASK_NAME") + .flatMap { it.javaLauncher } + doLast { println("Server Java: " + launcher.get().metadata.languageVersion) } + } + """.stripIndent() + + when: + run("printServerJava") + + then: "server runs with Java 17" + result.output.contains("Server Java: 17") + } }