Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ build/

# IntelliJ
out/

# Kotlin
.kotlin/
22 changes: 21 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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

Expand Down
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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:

Expand Down Expand Up @@ -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].

Expand Down Expand Up @@ -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:
Expand Down
5 changes: 3 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
4 changes: 3 additions & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -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
13 changes: 5 additions & 8 deletions gradlew

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

86 changes: 52 additions & 34 deletions gradlew.bat

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions src/main/kotlin/dependencies/Dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -114,4 +113,11 @@ internal object Dependencies {
}
}
}

private fun resolveBukkitVersion(group: String, apiVersion: String): String {
// Since 26.1, paper-api is published as '<version>.build.<number>-<channel>', 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"
}
}
2 changes: 1 addition & 1 deletion src/main/kotlin/extensions/Provider.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import java.util.*

internal fun <T> Property<T>.finalizeAndGet(): T {
internal fun <T : Any> Property<T>.finalizeAndGet(): T {
finalizeValue()
return get()
}
Expand Down
31 changes: 17 additions & 14 deletions src/main/kotlin/plugin/PluginYamlFeature.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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>("parsePluginYaml") {
pluginYaml.set(bukkitPluginYaml)
pluginYamlFile.set(findPluginYaml(mainSourceSet))
pluginYamlFile.set(sourcePluginYaml)

onlyIf { bukkit.generatePluginYaml.finalizeAndGet() }
}
Expand All @@ -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<SourceSet>): Provider<RegularFile> {
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 }
}
Expand Down
2 changes: 2 additions & 0 deletions src/main/kotlin/plugin/task/ParsePluginYaml.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading
Loading