Skip to main content

Plugin manifest

For Minecraft plugins, a second plugin publishes a manifest beside the jar. It says which Minecraft versions and platforms a build supports, which Java it needs and which plugins it depends on, with links to where they are found. A download site can read what a build needs without opening the jar.

plugins {
java
`maven-publish`
id("de.chojo.publishdata") version "2.1.0"
id("de.chojo.publishdata.manifest") version "2.1.0"
}

pluginManifest {
minecraft("1.20.4", "1.21.4") // both inclusive; leave out the upper bound if there is none
optional("PlaceholderAPI", min = "2.11.0") {
modrinth("placeholderapi")
spigot(6245)
hangar("HelpChat/PlaceholderAPI")
}
requires("ProtocolLib") {
link("https://github.com/dmulloy2/ProtocolLib")
}
put("discord", "https://discord.gg/…")
}

The manifest is published with the classifier manifest, as sample-1.4.0-manifest.json beside sample-1.4.0.jar, to every Maven publication of the project. It does not need the version plugin; any maven-publish setup works.

./gradlew generatePluginManifest

writes it to build/pluginManifest/manifest.json without publishing.

What comes from the plugin descriptor​

Whatever the build script leaves out is read from the processed plugin.yml or paper-plugin.yml:

FieldFrom the descriptorIn pluginManifest
namenamename = "…"
versionthe project version-
platformsbukkit for plugin.yml, paper for paper-plugin.yml, folia with folia-supported: trueplatforms("paper", "folia")
minecraftapi-version as the lower boundminecraft(min, max)
javathe toolchain's version, else the target compatibilityjava = 21
dependenciesdepend and softdepend, or dependencies.server of a paper-plugin.ymlrequires(…) and optional(…)
extra-put(key, value)

When both descriptors exist, the platforms of both count and the dependencies come from paper-plugin.yml.

A dependency declared in the build script refines the one of the same name from the descriptor (the name is compared without case), adding versions and links. Otherwise it is added after them.

plugin-yml​

A descriptor generated by plugin-yml is read the same way, since it is part of the processed resources. bukkit { } and paper { } give the name, apiVersion, the dependencies and foliaSupported, and pluginManifest { } adds the rest.

plugins {
id("de.eldoria.plugin-yml.paper") version "0.9.0"
id("de.chojo.publishdata.manifest") version "2.1.0"
}

paper {
apiVersion = "1.21"
serverDependencies {
register("Vault") { required = true }
}
}

pluginManifest {
minecraft("1.21", "1.21.4")
requires("Vault") { spigot(34315) }
}

Links of a dependency, in the order given:

CallLink
modrinth("slug")https://modrinth.com/plugin/slug
spigot(6245)https://www.spigotmc.org/resources/6245/
hangar("owner/slug")https://hangar.papermc.io/owner/slug
link("https://…")any http or https address

A malformed id or address fails the build. Each link is written with its full address, and the shortcuts also with their id.

The manifest​

{
"schema": 1,
"name": "Sample",
"version": "1.4.0",
"platforms": ["bukkit"],
"minecraft": {"min": "1.20.4", "max": "1.21.4"},
"java": 21,
"dependencies": [
{
"name": "PlaceholderAPI",
"required": false,
"min": "2.11.0",
"links": [{"type": "modrinth", "id": "placeholderapi", "url": "https://modrinth.com/plugin/placeholderapi"}]
}
],
"extra": {"discord": "https://discord.gg/…"}
}

Fields that are not set are left out. schema changes when a field changes meaning, so a reader can tell a manifest it does not understand.