Skip to content

These docs describe Bloom 0.1.0, a pre-release. APIs may change before 1.0, and Bloom is not on Maven Central yet (see Installation).

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:

build.gradle.ktsView source
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.")
}

Pick modules

Depend only on what you use; feature modules bring the core with them.

You needAdd
Messages, scheduler, eventsbloom-bukkit
Itemsbloom-items
Menus (includes items)bloom-gui
YAML configurationbloom-config
SQL storagebloom-storage
Unit-test helpersbloom-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.

build.gradle.kts
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

src/main/resources/plugin.ymlView source
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

MyPlugin.javaView source
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.