Installation
Add Bloom to a Gradle plugin project for legacy, modern or cross-version servers, and shade it correctly.
Bloom is a library you embed in your plugin: its classes are shaded into your jar and relocated into your own package. Nothing is installed on the server.
Choose your target
Bloom's modules are Java 8 bytecode except bloom-modern, which is Java 21. What you compile against decides which
servers your jar can run on.
Compile against spigot-api 1.8.8 as Java 8 bytecode and include both adapters. This is the setup the examples
use. It is verified by building the standalone template in bloom-examples/template:
repositories {
mavenCentral()
// Bloom is not on Maven Central yet. Either unzip bloom-<version>-central-bundle.zip from GitHub Releases and add
// maven(uri("path/to/unzipped-bundle")), or run `./gradlew publishToMavenLocal` in the Bloom repository.
mavenLocal()
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") // spigot-api
// spigot-api 1.8.8 depends on bungeecord-chat 1.8-SNAPSHOT, which only PaperMC's repository still serves.
maven("https://repo.papermc.io/repository/maven-public/")
}
java {
toolchain { languageVersion = JavaLanguageVersion.of(21) }
// The plugin is Java 8 bytecode but bundles Bloom's Java 21 modern adapter, which Bloom only loads on Java 21+.
disableAutoTargetJvm()
}
val bloomVersion = providers.gradleProperty("bloomVersion").getOrElse("0.1.0")
dependencies {
compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT") // compile against the oldest API you support
implementation("io.github.crownalonedev.bloom:bloom-gui:$bloomVersion") // menus + items + core
runtimeOnly("io.github.crownalonedev.bloom:bloom-legacy:$bloomVersion") // 1.7.10 - 1.8.9
runtimeOnly("io.github.crownalonedev.bloom:bloom-modern:$bloomVersion") // Paper 1.21.1 - 26.3.x
}
tasks.withType<JavaCompile>().configureEach {
options.release = 8
}
tasks.shadowJar {
archiveClassifier = ""
// Relocate Bloom into your own package so several plugins can embed different Bloom versions.
// The trailing dots matter: they stop the pattern from matching unrelated packages.
relocate("io.github.crownalonedev.bloom.", "com.example.myplugin.libs.bloom.")
}The same as cross-version, without bloom-modern and without disableAutoTargetJvm():
repositories {
mavenCentral()
mavenLocal()
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
maven("https://repo.papermc.io/repository/maven-public/") // bungeecord-chat for spigot-api 1.8.8
}
dependencies {
compileOnly("org.spigotmc:spigot-api:1.8.8-R0.1-SNAPSHOT")
implementation("io.github.crownalonedev.bloom:bloom-gui:0.1.0")
runtimeOnly("io.github.crownalonedev.bloom:bloom-legacy:0.1.0")
}
tasks.withType<JavaCompile>().configureEach {
options.release = 8
}Compile against paper-api with Java 21 and include only bloom-modern. You can then use Paper APIs directly in
your own code:
repositories {
maven("https://repo.papermc.io/repository/maven-public/")
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.11-R0.1-SNAPSHOT")
implementation("io.github.crownalonedev.bloom:bloom-gui:0.1.0")
runtimeOnly("io.github.crownalonedev.bloom:bloom-modern:0.1.0")
}
tasks.withType<JavaCompile>().configureEach {
options.release = 21
}Pick modules
Depend only on what you use; feature modules bring the core with them.
| You need | Add |
|---|---|
| Messages, scheduler, events | bloom-bukkit |
| Items | bloom-items |
| Menus (includes items) | bloom-gui |
| YAML configuration | bloom-config |
| SQL storage | bloom-storage |
| Unit-test helpers | bloom-testing (test scope) |
Relocate Bloom
Every plugin that embeds Bloom must relocate it, so two plugins with different Bloom versions never share classes.
Patterns must end with a dot, otherwise io.github.crownalonedev.bloom would also match your own package if it
happens to start the same way.
tasks.shadowJar {
relocate("io.github.crownalonedev.bloom.", "com.example.myplugin.libs.bloom.")
relocate("org.yaml.snakeyaml.", "com.example.myplugin.libs.snakeyaml.") // with bloom-config
relocate("com.zaxxer.hikari.", "com.example.myplugin.libs.hikari.") // with bloom-storage
relocate("org.slf4j.", "com.example.myplugin.libs.slf4j.") // with bloom-storage
}Why disableAutoTargetJvm
Gradle refuses to add a Java 21 library to a Java 8 project by default. Cross-version plugins need
java { disableAutoTargetJvm() } because bloom-modern is Java 21 bytecode. This is safe: Bloom loads that adapter
only on Paper servers, which require Java 21 or newer.
plugin.yml
name: MyPlugin
version: '${version}'
main: com.example.myplugin.MyPlugin
# Ignored by 1.7/1.8; tells modern Paper this is not a legacy (pre-1.13) plugin.
api-version: '1.21'Your first class
public final class MyPlugin extends JavaPlugin {
private Bloom bloom;
@Override
public void onEnable() {
bloom = Bloom.enable(this);
bloom.messages().send(getServer().getConsoleSender(), "&dHello from Bloom on " + bloom.platform().describe());
}
@Override
public void onDisable() {
if (bloom != null) {
bloom.shutdown();
}
}
}Build with ./gradlew shadowJar and copy build/libs/<name>.jar into the server's plugins folder. The console
shows a line like Bloom 0.1.0 · Paper 1.21.11 (Java 21.0.5) · adapter: modern.
Standalone runtime (planned)
A shared Bloom runtime plugin that other plugins depend on is planned but not available. Embedding, as described above, is the only supported distribution today. See Distribution.