kdoc( javadoc): SpigotPlugin.kt
The Spigot plugin provides the following features:
-
Generate 'plugin.yml' with the main detected automatically
-
Debug feature: task
debugProjectName, idea Run ConfigurationDebugProjectName/RunProjectName -
Shortcuts for dependency and repository.
The plugin requires Gradle 9.0+, the latest version is recommended.
To update your gradle wrapper:
gradlew wrapper --gradle-version 9.2.1 --distribution-type all
settings.gradle.kts
dependencyResolutionManagement {
repositories {
mavenCentral()
}
versionCatalogs {
create("spigots") {
from("io.typst:spigot-catalog:1.0.0")
}
create("commons") {
from("io.typst:common-catalog:1.1.0")
}
}
}build.gradle.kts
plugins {
java
alias(spigots.plugins.spigot)
alias(commons.plugins.ideaExt) // optional, for debug Run Configurations
}
repositories {
mavenCentral()
spigotRepos {
papermc()
}
}
dependencies {
compileOnly(spigots.paper.api)
}Groovy (settings.gradle)
dependencyResolutionManagement {
repositories {
mavenCentral()
}
versionCatalogs {
create('spigots') {
from('io.typst:spigot-catalog:1.0.0')
}
create('commons') {
from('io.typst:common-catalog:1.1.0')
}
}
}Groovy (build.gradle)
plugins {
id 'java'
alias papers.plugins.spigot
alias commons.plugins.ideaExt // optional
}
repositories {
mavenCentral()
spigotRepos {
papermc()
}
}
dependencies {
compileOnly papers.paper.api
}Groovy DSL
plugins {
id 'io.typst.spigradle.spigot' version '4.0.2'
id 'org.jetbrains.gradle.plugin.idea-ext' version '1.3' // optional
}Kotlin DSL
plugins {
id("io.typst.spigradle.spigot") version "4.0.2"
id("org.jetbrains.gradle.plugin.idea-ext") version "1.3" // optional
}The plugin.yml file will be generated by task generateSpigotPluginDescription based on the configuration of
spigot, included into output jars automatically.
Basically the properties 'main', 'name' and 'version' defaults to auto-detected main, project.name, project.version respectively. So if we create a simple plugin that just needs those properties, we don't need any configuration. Only pay attention to your unique implementation.
You can configure all properties of plugin.yml in spigot {} block.
The plugin automatically detects your main plugin class using bytecode analysis (ASM). It scans compiled .class files
to find classes that
extend JavaPlugin.
How it works:
- Scans compiled bytecode (not source code) for faster and more reliable detection
- Finds non-abstract, public classes extending
org.bukkit.plugin.java.JavaPlugin - Supports complex inheritance hierarchies
- Incremental: only scans changed files for faster builds
- Automatically sets the
mainproperty inplugin.yml
Manual override: If you need to manually specify the main class:
spigot {
main.set("com.example.MyCustomMain")
}For more details, see the Main Class Detection section.
spigot extension - SpigotExtension
The description of your plugin for a plugin.yml.
The 'main' property will be set to the class auto-detected
About the plugin.yml, See plugin-yml wiki
Groovy Example
spigot {
authors = ['Me']
depend = ['ProtocolLib', 'Vault']
softDepend = ['WorldEdit']
apiVersion = '1.15'
load = "STARTUP"
libraries = ['my:lib:1.0.0', 'my:lib2:1.0.0']
commands {
register('give') {
aliases = ['giv', 'i']
description = 'Give command.'
permission = 'test.foo'
permissionMessage = 'You do not have the permission!'
usage = '/<command> [item] [amount]'
}
}
permissions {
register('test.foo') {
description = 'Allows foo command'
defaults = 'true'
}
register('test.*') {
description = 'Wildcard permission'
defaults = 'op'
children = ['test.foo': true]
}
}
}Kotlin Example
spigot {
authors = listOf("Me")
depend = listOf("ProtocolLib")
softDepend = listOf("WorldEdit")
apiVersion = "1.15"
load = "STARTUP"
commands {
register("give") {
aliases = listOf("i")
description = "Give command."
permission = "test.foo"
permissionMessage = "You do not have permission!"
usage = "/<command> [test|stop]"
}
}
permissions {
register("test.foo") {
description = "Allows foo command"
defaults = "true"
}
register("test.*") {
description = "Wildcard permission"
defaults = "op"
children = mapOf("test.foo" to true)
}
}
}Without type-safe accessors:
configure<SpigotExtension> {
authors = listOf("Me")
// ...
}debugSpigot extension - DebugExtension
Note:
debugSpigotis a configuration extension, NOT a task. The actual task is nameddebugProjectName( e.g.,debugMyPlugin).
To see the platform defaults, see the dokka(javadoc) of SpigotBasePlugin
Available properties:
| Property | Type | Default | Description |
|---|---|---|---|
version |
Property<String> |
- | Paper/Minecraft version to download (e.g., "1.21.8") |
eula |
Property<Boolean> |
false |
Auto-accept Minecraft EULA |
jvmDebugPort |
Property<Int> |
5005 |
Port for remote JVM debugging |
downloadSoftDepend |
Property<Boolean> |
false |
Also download softDepends plugins |
jvmArgs |
ListProperty<String> |
platform defaults | JVM arguments (e.g., -Xmx2G) |
programArgs |
ListProperty<String> |
platform defaults | Server program arguments (e.g., nogui) |
javaVersion |
Property<JavaLanguageVersion> |
project toolchain | Java version for the server |
javaHome |
Property<Directory> |
resolved from javaVersion |
Java installation directory |
Example:
debugSpigot {
version = "1.21.8"
eula = true
jvmDebugPort = 5005
downloadSoftDepend = true
// Use append() (Gradle 8.7+) to preserve defaults:
jvmArgs.append("-Xmx4G")
programArgs.append("--world myworld")
}debugSpigot {
version = "1.21.8"
eula = true
jvmDebugPort = 5005
downloadSoftDepend = true
// Use append() (Gradle 8.7+) to preserve defaults:
jvmArgs.append("-Xmx4G")
programArgs.append("--world myworld")
}Warning: Using
add(),set(), orempty()onjvmArgs/programArgswill discard platform defaults. Useappend()orappendAll()(Gradle 8.7+) to preserve defaults.
Declaring dependencies to libraries in plugin.yml is the recommended approach instead of shading jar.
You can use the compileOnlySpigot dependency configuration to declare as compileOnly and libraries in plugin.yml.
To see the dependency graph of compileOnlySpigot, execute the dependencies Gradle task and look at the spigotLibrariesClasspath section. also you can see the result plugin.yml in build/tmp/generateSpigotPluginDescription.
The spigotLibrariesClasspath configuration resolves only root level dependencies.
dependencies {
compileOnlySpigot("org.ahocorasick:ahocorasick:0.6.3")
}All tasks supports UP-TO-DATE check.
detectSpigotEntrypoints - SubclassDetection
Finds the main class extends org.bukkit.plugin.java.JavaPlugin.
generateSpigotPluginDescription - YamlGenerate
Depends on: detectSpigotEntrypoints
Generates the description file 'plugin.yml'.
debugProjectName - Exec
Depends on: prepareProjectName
Runs a local Paper server with your plugin for debugging. This task orchestrates the complete debug workflow:
What it does:
- Downloads Paper server (via
downloadPaper) - Fetches the specified Paper version from PaperMC API if not already cached - Prepares plugin dependencies (via
preparePluginDependencies) - Resolves plugins listed independs/softDepends:
- First tries to copy from your project's
compileClasspath - Falls back to downloading from SpigotMC (via Spiget API) if not found
- Copies your plugin JAR (via
copyArtifactJar) - Copies the built plugin to the debug server's plugins folder - Creates starter scripts (via
createJavaDebugScript) - Generates platform-specific scripts:
starter.batfor Windowsstarterfor Unix/Linux/Mac
- Launches the server - Opens a new terminal window and runs the server
IntelliJ IDEA Run Configurations:
Spigradle automatically creates two run configurations (NOTE: These are only generated if the plugin
org.jetbrains.gradle.plugin.idea-ext is applied):
DebugProjectName- Remote JVM Debug ⭐ Recommended
- Type: Remote JVM Debug configuration
- Purpose: Attaches debugger to an already-running server process
- Recommended workflow:
- Run
debugProjectNametask via IntelliJ's terminal or "Run Gradle Task" - Server starts in a new terminal window with remote debugging enabled on port 5005
- Click the "🐞 Debug" button on this configuration to attach the debugger
- Run
- Advantages:
- Keeps IntelliJ lightweight - server runs in separate terminal, not managed by IDE
- Clean separation between server output and IDE
- Better performance - IDE doesn't handle server I/O
- When to use: Standard debugging workflow (recommended for regular use)
RunProjectName- JarApplication
- Type: JarApplication run configuration
- Purpose: All-in-one server launch directly from IntelliJ
- Usage:
- Click the "▶ Run" button to start the server normally
- Click the "🐞 Debug" button to start the server AND attach debugger in one step
- Note: Makes IntelliJ heavier as it manages the server process directly; You need to click the
Sync All Gradle Projectsbutton in IDEA if you change the debugSpigot extension. - When to use: Only when you want absolute convenience and don't mind the performance impact
Directory structure:
- Server directory:
MY_PROJECT/.gradle/spigradle-debug/paper/ - Global JAR cache:
GRADLE_USER_HOME/spigradle-debug-jars/paper/VERSION/paper.jar - Plugin dependencies:
MY_PROJECT/.gradle/spigradle-debug/paper/plugins/
Configuration:
See debugSpigot extension for configuration options like version, EULA acceptance, JVM arguments, and debug port.
With Spigradle 1.3.0+, you can use the MockBukkit without any special code.
If you use less than 1.3.0, add it in build.gradle:
task copyPluginYaml(type: Copy, dependsOn: spigotPluginYaml) {
from(new File(spigotPluginYaml.temporaryDir, 'plugin.yml'))
into(sourceSets.test.output.resourcesDir)
}
tasks.test.dependsOn(copyPluginYaml)Prerequisite: https://docs.papermc.io/paper/dev/userdev/
plugins {
// ...
alias(spigots.plugins.paperweight.userdev)
}
dependencies {
paperweight.paperDevBundle(spigots.versions.spigot.api) // this is a replacement for spigot-api/paper-api
// ...
}
tasks {
assemble {
dependsOn(reobfJar)
}
}
debugSpigot {
// ...
jarFile = tasks.reobfJar.flatMap { it.outputJar } // For debug, to copy the reobfJar
}
spigot-plugin-template by @Silthus
BukkitJavaGradle by @portlek