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).

Distribution

Embedding Bloom in your plugin today, the planned standalone runtime, and licensing for closed-source plugins.

Embedded (supported)

Each plugin shades its own copy of Bloom and relocates it into its own package. Two plugins on one server can use different Bloom versions without conflict, and server owners install nothing extra.

At startup Bloom checks how it was loaded. If its classes came from another plugin's class loader, it logs a warning: that happens when a plugin shades Bloom without relocating it, and another plugin then picks up those classes. With BloomOptions.debug(true) Bloom also tells you when your own copy is not relocated.

Check your jar with bloom-doctor

bloom-doctor inspects the jar you are about to ship, before a server does:

  • plugin.yml exists and its main class is in the jar;
  • Bloom, SnakeYAML, HikariCP and SLF4J are relocated, and the Bukkit API is not bundled;
  • at least one platform adapter is included (and which server families that covers);
  • the bytecode level fits the oldest server you target (Java 8 for 1.7.10 – 1.8.9);
  • with API jars given, every Bukkit/Paper method, field and class your jar uses exists with the same shape on each target server. This is what catches NoSuchMethodError, NoSuchFieldError and IncompatibleClassChangeError (for example InventoryView, a class on 1.8 and an interface on 1.21) without booting a server.

Download bloom-doctor-0.1.0-all.jar from GitHub Releases (or build it with ./gradlew :bloom-doctor:shadowJar), then:

Shell
java -jar bloom-doctor-0.1.0-all.jar build/libs/my-plugin.jar \
  --legacy-api spigot-1.8.8=spigot-api-1.8.8-R0.1-SNAPSHOT.jar,bungeecord-chat-1.8-SNAPSHOT.jar \
  --modern-api paper-1.21.11=paper-api-1.21.11-R0.1-SNAPSHOT.jar,adventure-api-4.26.1.jar,...

List the API jar together with its dependencies for each target (Gradle: the compileClasspath of a project that depends on that API). The legacy adapter is not checked against modern APIs and vice versa, because Bloom never loads it there. If your own code has version-specific classes that you only load after a version check, exclude their package with --exclude com.example.myplugin.v1_21. The exit code is 1 when there is an error, so the doctor can run in CI. Bloom itself runs it on every example plugin in its build.

Standalone runtime (planned)

A Bloom plugin that others depend on, instead of shading, is on the roadmap. It needs version negotiation between plugins and a lifecycle that survives individual plugins reloading. It will not be offered until both exist and are tested; until then, embed Bloom.

Licensing

Bloom is MIT licensed. You can embed it in closed-source and commercial plugins; keep the license notice, for example in your jar's META-INF or your documentation.