bloom-api
Bloom API: stable, platform-neutral contracts (platform model, capabilities, services, scheduling, text, utilities).
io.github.crownalonedev.bloom.api
BloomException class
public class BloomException extends RuntimeException
Base class for all exceptions thrown by Bloom. Bloom exceptions are unchecked and carry developer-facing messages that explain what went wrong and, where possible, how to fix it.
Since 0.1.0
2 members
public BloomException(String message)
Creates an exception with a message.
- message
- developer-facing description of the problem
public BloomException(String message, Throwable cause)
Creates an exception with a message and cause.
- message
- developer-facing description of the problem
- cause
- underlying cause
io.github.crownalonedev.bloom.api
BloomStartupException class
public class BloomStartupException extends BloomException
Thrown when Bloom cannot start, for example because the server version is unsupported or the required platform adapter is missing from the plugin jar. The message always names the detected platform and the corrective action.
Since 0.1.0
2 members
public BloomStartupException(String message)
Creates a startup exception.
- message
- developer-facing description of the problem and fix
public BloomStartupException(String message, Throwable cause)
Creates a startup exception with a cause.
- message
- developer-facing description of the problem and fix
- cause
- underlying cause
io.github.crownalonedev.bloom.api
BloomVersion class
public final class BloomVersion
The Bloom release this code was built as. Generated at build time.
Since 0.1.0
1 member
public static final String VERSION
The Bloom version string, e.g. "0.1.0" or "0.2.0-SNAPSHOT".
io.github.crownalonedev.bloom.api
UnsupportedCapabilityException class
public class UnsupportedCapabilityException extends BloomException
Thrown when code requires a platform capability that the running server does not provide, for example boss bars on a 1.8 server. Avoid this exception by checking capabilities().has(capability) first, or by choosing an API variant with a documented fallback.
Since 0.1.0
2 members
public UnsupportedCapabilityException(Capability capability, String platformDescription, String feature)
Creates the exception.
- capability
- the missing capability
- platformDescription
- human-readable description of the running platform
- feature
- what the caller attempted, e.g. "Messenger.actionBar"
public Capability capability()
Returns the capability that was required.
Returns the missing capability
io.github.crownalonedev.bloom.api.lifecycle
LifecycleState enum
public final enum LifecycleState
Lifecycle states of a Bloom instance.
Since 0.1.0
8 members
public static LifecycleState[] values()
public static LifecycleState valueOf(String name)
- name
- String
NEW
Created but not yet started.
STARTING
Starting: detecting the platform and enabling the adapter.
RUNNING
Running; all services are usable.
STOPPING
Shutting down: services are being closed.
STOPPED
Shut down. Services must not be used.
FAILED
Startup failed; the instance cannot be used.
io.github.crownalonedev.bloom.api.lifecycle
Terminable interface
public interface Terminable extends AutoCloseable
A resource that can be closed, such as a scheduled task, an event subscription or a service. Unlike AutoCloseable.close, close does not throw checked exceptions and must be idempotent: closing twice has no further effect.
Since 0.1.0
2 members
public void close()
Releases the resource. Calling this more than once has no further effect.
public boolean isClosed()
Returns whether this resource has been closed.
Returns true once close has completed
io.github.crownalonedev.bloom.api.platform
Capabilities class
public final class Capabilities
An immutable set of capabilities available on the running platform.
Since 0.1.0
8 members
public static Capabilities of(Collection<Capability> present, String platformDescription)
Creates a capability set.
- present
- available capabilities
- platformDescription
- description of the platform, used in error messages
Returns the capability set
public static Capabilities none(String platformDescription)
Creates an empty capability set.
- platformDescription
- description of the platform
Returns a set with no capabilities
public boolean has(Capability capability)
Returns whether a capability is available.
- capability
- capability to check
Returns true if available
public void require(Capability capability, String feature)
Throws if a capability is unavailable.
- capability
- required capability
- feature
- description of the feature being used, included in the error message
Throws UnsupportedCapabilityException if the capability is unavailable
public Set<Capability> available()
Returns the available capabilities.
Returns unmodifiable set
public Set<Capability> unavailable()
Returns the capabilities that are not available.
Returns unmodifiable set
public String platformDescription()
Returns the platform description used in error messages.
Returns platform description
io.github.crownalonedev.bloom.api.platform
Capability enum
public final enum Capability
Optional platform features whose availability depends on the server version or implementation. The active adapter decides which capabilities are present, in some cases by probing the running server (for example, legacy NBT access through reflection). Use Capabilities.has before calling features that are not universally available.
Since 0.1.0
17 members
public static Capability[] values()
public static Capability valueOf(String name)
- name
- String
ADVENTURE_TEXT
Native Adventure text components (Paper).
MINIMESSAGE
Full MiniMessage parsing. Legacy servers get a documented subset converted to legacy colours instead.
HEX_COLORS
RGB/hex colours in text (1.16+).
ACTION_BAR
Action bar messages. Legacy 1.8 servers require a successful NMS reflection probe.
TITLES
Title and subtitle messages.
TITLE_TIMINGS
Custom fade-in/stay/fade-out timings for titles.
COMPONENT_INVENTORY_TITLES
Component-based inventory titles (allows MiniMessage formatting and titles over 32 characters).
PERSISTENT_DATA_CONTAINER
Bukkit PersistentDataContainer on items.
ITEM_NBT_TAGS
Custom NBT tags on items through version-specific reflection (legacy).
ITEM_FLAGS
Item flags such as HIDE_ENCHANTS (1.8+).
UNBREAKABLE_ITEMS
Unbreakable items.
CUSTOM_MODEL_DATA
Custom model data on items (1.14+).
LEGACY_DATA_VALUES
Numeric data/durability values selecting item variants, e.g. WOOL:14 (pre-1.13).
public String description()
Returns a short human-readable description.
Returns description used in error messages and diagnostics
io.github.crownalonedev.bloom.api.platform
JavaRuntime class
public final class JavaRuntime
Describes the Java runtime the server is running on.
Since 0.1.0
7 members
public static JavaRuntime current()
Describes the current JVM.
Returns the current runtime
public static JavaRuntime of(String specificationVersion, String fullVersion, String vendor)
Creates a runtime description from system property values.
- specificationVersion
- value of java.specification.version, e.g. "1.8" or "21"
- fullVersion
- value of java.version
- vendor
- value of java.vendor
Returns the runtime description
public int featureVersion()
Returns the Java feature version.
Returns e.g. 8, 21 or 25
public String fullVersion()
Returns the full version string.
Returns e.g. "1.8.0_472" or "21.0.11"
public String vendor()
Returns the runtime vendor.
Returns vendor name
public boolean isAtLeast(int feature)
Returns whether the runtime is at least the given feature version.
- feature
- feature version to compare with
Returns true if featureVersion() >= feature
io.github.crownalonedev.bloom.api.platform
MinecraftVersion class
public final class MinecraftVersion implements Comparable<MinecraftVersion>
An immutable Minecraft release version such as 1.8.8, 1.21.11 or 26.3. Both the classic 1.x.y scheme and Mojang's year-based scheme (26.1, 26.3) are represented as major.minor.patch. Because 1 < 26, natural ordering is correct across schemes. Pre-release suffixes (-pre3, -rc1) are ignored when parsing.
Since 0.1.0
23 members
public static final MinecraftVersion V1_7_10
Minecraft 1.7.10, the only supported 1.7 release.
public static final MinecraftVersion V1_8
Minecraft 1.8 (1.8.0).
public static final MinecraftVersion V1_8_8
Minecraft 1.8.8, the most common legacy PvP version.
public static final MinecraftVersion V1_8_9
Minecraft 1.8.9, the last 1.8 release.
public static final MinecraftVersion V1_21_1
Minecraft 1.21.1.
public static final MinecraftVersion V1_21_11
Minecraft 1.21.11, the last 1.x release.
public static final MinecraftVersion V26_1
Minecraft 26.1, the first year-based release.
public static MinecraftVersion of(int major, int minor, int patch)
Creates a version.
- major
- major component, 1 for classic versions or the year for year-based versions
- minor
- minor component
- patch
- patch component
Returns the version
public static MinecraftVersion of(int major, int minor)
Creates a version with patch 0.
- major
- major component
- minor
- minor component
Returns the version
public static MinecraftVersion parse(String text)
Parses a version from the start of a string such as "1.8.8", "1.21.11-R0.1-SNAPSHOT" or "26.3.build.177-stable".
- text
- text beginning with a version
Returns the parsed version
Throws IllegalArgumentException if the text does not start with a version
public static Optional<MinecraftVersion> tryParse(String text)
Parses a version from the start of a string, returning empty instead of throwing.
- text
- text beginning with a version, may be null
Returns the parsed version, or empty
public static Optional<MinecraftVersion> detect(String bukkitVersion, String serverVersion)
Determines the Minecraft version from the strings a Bukkit-family server reports. The "(MC: x.y.z)" marker in Server#getVersion() is preferred because it always contains the game version; Server#getBukkitVersion() is used as a fallback.
- bukkitVersion
- value of Server#getBukkitVersion(), may be null
- serverVersion
- value of Server#getVersion(), may be null
Returns the detected version, or empty if neither string contains one
public int major()
Returns the major component.
Returns major component
public int minor()
Returns the minor component.
Returns minor component
public int patch()
Returns the patch component.
Returns patch component, 0 if the version string had none
public boolean isAtLeast(MinecraftVersion other)
Returns whether this version is the same as or newer than another.
- other
- version to compare with
Returns true if this >= other
public boolean isBefore(MinecraftVersion other)
Returns whether this version is older than another.
- other
- version to compare with
Returns true if this < other
public boolean isBetween(MinecraftVersion min, MinecraftVersion max)
Returns whether this version lies within an inclusive range.
- min
- inclusive lower bound
- max
- inclusive upper bound
Returns true if min <= this <= max
public boolean isSameLine(MinecraftVersion other)
Returns whether this version shares major and minor components with another, e.g. 1.8.3 and 1.8.8.
- other
- version to compare with
Returns true if both belong to the same release line
public int compareTo(MinecraftVersion o)
- o
- MinecraftVersion
public boolean equals(Object o)
- o
- Object
public String toString()
Formats the version the way Mojang does: 1.8 rather than 1.8.0.
Returns the version string
io.github.crownalonedev.bloom.api.platform
PlatformFamily enum
public final enum PlatformFamily
The platform families Bloom ships adapters for. Each family is served by one adapter module.
Since 0.1.0
6 members
public static PlatformFamily[] values()
public static PlatformFamily valueOf(String name)
- name
- String
LEGACY
Bukkit/Spigot 1.7.10 to 1.8.9 on Java 8. Served by bloom-legacy.
MODERN
Paper 1.21.x and 26.x on Java 21+. Served by bloom-modern.
public String id()
Returns the short identifier used in logs and configuration.
Returns "legacy" or "modern"
public String adapterModule()
Returns the Bloom artifact that contains this family's adapter.
Returns artifact id, e.g. "bloom-legacy"
io.github.crownalonedev.bloom.api.platform
PlatformInfo class
public final class PlatformInfo
Immutable description of the server Bloom is running on.
Since 0.1.0
9 members
public PlatformInfo(ServerSoftware software, String serverName, String serverVersion, String bukkitVersion, MinecraftVersion minecraftVersion, JavaRuntime javaRuntime)
Creates a platform description.
- software
- detected implementation
- serverName
- value of Server#getName()
- serverVersion
- value of Server#getVersion()
- bukkitVersion
- value of Server#getBukkitVersion()
- minecraftVersion
- detected game version
- javaRuntime
- running Java runtime
public ServerSoftware software()
Returns the detected server implementation.
Returns server software
public String serverName()
Returns the name the server reports, e.g. "Paper" or "CraftBukkit".
Returns server name
public String serverVersion()
Returns the raw server version string.
Returns e.g. "git-Spigot-db6de12-18fbb24 (MC: 1.8.8)"
public String bukkitVersion()
Returns the raw Bukkit API version string.
Returns e.g. "1.8.8-R0.1-SNAPSHOT"
public MinecraftVersion minecraftVersion()
Returns the Minecraft version.
Returns game version
public JavaRuntime javaRuntime()
Returns the Java runtime.
Returns Java runtime
public String describe()
Returns a short description such as "Paper 1.21.11 (Java 21.0.11)".
Returns description for logs and error messages
io.github.crownalonedev.bloom.api.platform
ServerSoftware enum
public final enum ServerSoftware
Server implementations Bloom can recognise. Recognition does not imply support; see PlatformFamily and the compatibility matrix.
Since 0.1.0
12 members
public static ServerSoftware[] values()
public static ServerSoftware valueOf(String name)
- name
- String
CRAFTBUKKIT
CraftBukkit without Spigot patches.
PAPER_SPIGOT
PaperSpigot, the legacy (1.7/1.8) Paper fork of Spigot.
PAPER
Paper (1.9 and newer).
PAPER_FORK
A Paper fork such as Purpur or Pufferfish; Paper API is available.
FOLIA
Folia, Paper's regionised fork. Not supported by Bloom yet: its scheduler model differs.
MOCKBUKKIT
MockBukkit test server (implements Paper API).
UNKNOWN
Unrecognised implementation.
public String displayName()
Returns a human-readable name.
Returns display name
public boolean hasPaperApi()
Returns whether this implementation exposes the modern Paper API (Adventure, PDC, etc.).
Returns true for Paper, Paper forks, Folia and MockBukkit
io.github.crownalonedev.bloom.api.platform
SupportDecision class
public final class SupportDecision
Result of SupportPolicy.evaluate.
Since 0.1.0
4 members
public boolean isSupported()
Returns whether Bloom may start.
Returns true if an adapter family was selected
public PlatformFamily family()
Returns the selected adapter family.
Returns family
Throws IllegalStateException if unsupported
public boolean isUntested()
Returns whether the platform is newer than the supported range and was only accepted because the developer opted in.
Returns true for an explicitly allowed untested version
public String reason()
Returns why the platform is unsupported.
Returns explanation, or null if supported
io.github.crownalonedev.bloom.api.platform
SupportPolicy class
public final class SupportPolicy
The single source of truth for which platforms Bloom will start on. Runtime support ranges are deliberately conservative. Being inside a range means an adapter exists and its code was compile-verified against that API; the test status of each version is tracked separately in docs/architecture/COMPATIBILITY.md.
Since 0.1.0
6 members
public static final VersionRange LEGACY
Legacy family: 1.7.10 through 1.8.9.
public static final List<VersionRange> MODERN
Modern family ranges: Paper 1.21.1 - 1.21.11, then 26.1.x - 26.3.x.
public static final int LEGACY_MIN_JAVA
Minimum Java feature version for the legacy family.
public static final int MODERN_MIN_JAVA
Minimum Java feature version for the modern family (the modern adapter is Java 21 bytecode).
public static MinecraftVersion newestModern()
Returns the newest Minecraft version covered by a modern range.
Returns newest supported modern version (patch may be Integer.MAX_VALUE)
public static SupportDecision evaluate(ServerSoftware software, MinecraftVersion version, JavaRuntime java, boolean allowNewerUntested)
Decides whether and how Bloom can run on a platform.
- software
- detected server implementation
- version
- detected Minecraft version
- java
- running Java runtime
- allowNewerUntested
- whether the developer opted into running the modern adapter on Paper versions newer than the newest supported one
Returns the decision, never null
io.github.crownalonedev.bloom.api.platform
VersionRange class
public final class VersionRange
An inclusive range of Minecraft versions.
Since 0.1.0
6 members
public static VersionRange between(MinecraftVersion min, MinecraftVersion max)
Creates an inclusive range.
- min
- inclusive lower bound
- max
- inclusive upper bound
Returns the range
public static VersionRange lineFrom(int major, int minor, int minPatch)
Creates a range covering every patch release of one release line from a minimum patch, e.g. lineFrom(26, 3, 0) covers 26.3, 26.3.1, 26.3.2 and so on.
- major
- major component
- minor
- minor component
- minPatch
- first included patch
Returns the range
public MinecraftVersion min()
Returns the inclusive lower bound.
Returns lower bound
public MinecraftVersion max()
Returns the inclusive upper bound.
Returns upper bound; its patch is Integer.MAX_VALUE for open release lines
public boolean contains(MinecraftVersion version)
Tests whether a version lies in this range.
- version
- version to test
Returns true if included
io.github.crownalonedev.bloom.api.scheduler
BloomScheduler interface
public interface BloomScheduler
Plugin-owned task scheduling with automatic cleanup. Every task is owned by the Bloom instance that created it and is cancelled when Bloom shuts down. Exceptions thrown by tasks are caught and logged with the task's origin; they never kill the scheduler. Threading rules • sync* tasks run on the main server thread. Use them for anything that touches worlds, entities, players, inventories or most other Bukkit API. • async* tasks run on a background thread. Use them for I/O, computation and network calls. Never modify worlds, entities or inventories from an async task: hop back with sync or mainThreadExecutor. Delays and periods are in server ticks (20 per second at full speed) unless a Duration overload is used. A delay of 0 means "the next tick".
Since 0.1.0
15 members
public boolean isPrimaryThread()
Returns whether the calling thread is the main server thread.
Returns true on the main thread
public void ensurePrimaryThread(String operation)
Throws if not called from the main server thread. Use at the start of methods that touch game state.
- operation
- what the caller is doing, used in the error message
Throws IllegalStateException if called from another thread
public ScheduledTask sync(Runnable task)
Runs a task on the main thread on the next tick.
- task
- task to run
Returns task handle
public ScheduledTask syncLater(Runnable task, long delayTicks)
Runs a task on the main thread after a delay.
- task
- task to run
- delayTicks
- delay in ticks, >= 0
Returns task handle
public ScheduledTask syncLater(Runnable task, Duration delay)
Runs a task on the main thread after a delay.
- task
- task to run
- delay
- delay, rounded up to whole ticks
Returns task handle
public ScheduledTask syncRepeating(Consumer<ScheduledTask> task, long delayTicks, long periodTicks)
Runs a task repeatedly on the main thread. The task receives its own handle so it can cancel itself.
- task
- task to run; receives its handle
- delayTicks
- initial delay in ticks, >= 0
- periodTicks
- period in ticks, >= 1
Returns task handle
public ScheduledTask syncRepeating(Consumer<ScheduledTask> task, Duration delay, Duration period)
Runs a task repeatedly on the main thread.
- task
- task to run; receives its handle
- delay
- initial delay
- period
- period, at least one tick
Returns task handle
public ScheduledTask async(Runnable task)
Runs a task on a background thread as soon as possible.
- task
- task to run; must not touch game state
Returns task handle
public ScheduledTask asyncLater(Runnable task, long delayTicks)
Runs a task on a background thread after a delay.
- task
- task to run; must not touch game state
- delayTicks
- delay in ticks
Returns task handle
public ScheduledTask asyncRepeating(Consumer<ScheduledTask> task, long delayTicks, long periodTicks)
Runs a task repeatedly on a background thread.
- task
- task to run; receives its handle; must not touch game state
- delayTicks
- initial delay in ticks
- periodTicks
- period in ticks, >= 1
Returns task handle
public <T> CompletableFuture<T> supplySync(Supplier<T> supplier)
Computes a value on the main thread. If already on the main thread the supplier still runs on the next tick, so the behaviour is the same from every caller.
- supplier
- computation; may touch game state
Returns future completed on the main thread with the result or the thrown exception
public <T> CompletableFuture<T> supplyAsync(Supplier<T> supplier)
Computes a value on a background thread.
- supplier
- computation; must not touch game state
Returns future completed with the result or the thrown exception
public Executor mainThreadExecutor()
Returns an executor that runs tasks on the main thread. Useful for future.thenAcceptAsync(result -> ..., scheduler.mainThreadExecutor()).
Returns main-thread executor owned by this scheduler
public Executor asyncExecutor()
Returns an executor that runs tasks on background threads owned by this scheduler.
Returns async executor
public int activeTaskCount()
Returns the number of tasks that are scheduled and not yet finished or cancelled.
Returns active task count
io.github.crownalonedev.bloom.api.scheduler
ScheduledTask interface
public interface ScheduledTask extends Terminable
Handle to a task submitted to a BloomScheduler. close is equivalent to cancel.
Since 0.1.0
7 members
public void cancel()
Cancels the task. A one-shot task that already ran is unaffected; a repeating task will not run again. Idempotent.
public boolean isCancelled()
Returns whether the task was cancelled (explicitly or by scheduler shutdown).
Returns true if cancelled
public boolean isDone()
Returns whether a one-shot task has finished running. Always false for repeating tasks that were not cancelled.
Returns true if finished
public boolean isAsync()
Returns whether the task runs off the main server thread.
Returns true for async tasks
public boolean isRepeating()
Returns whether the task repeats.
Returns true for repeating tasks
public default void close()
public default boolean isClosed()
io.github.crownalonedev.bloom.api.scheduler
Ticks class
public final class Ticks
Conversions between server ticks and Durations. One tick is 50 ms at the nominal 20 TPS.
Since 0.1.0
5 members
public static final int PER_SECOND
Nominal ticks per second.
public static final long MILLIS_PER_TICK
Nominal milliseconds per tick.
public static long from(Duration duration)
Converts a duration to ticks, rounding up so that a positive duration never becomes zero ticks.
- duration
- non-negative duration
Returns number of ticks
Throws IllegalArgumentException if the duration is negative
public static Duration toDuration(long ticks)
Converts ticks to a duration.
- ticks
- number of ticks
Returns the nominal duration
public static long seconds(long seconds)
Converts seconds to ticks.
- seconds
- seconds
Returns ticks
io.github.crownalonedev.bloom.api.service
ServiceRegistry interface
public interface ServiceRegistry
A simple, type-keyed registry of services owned by one Bloom instance. Services that implement Terminable or AutoCloseable are closed automatically, in reverse registration order, when Bloom shuts down. All methods are thread-safe.
Since 0.1.0
6 members
public <T> void register(Class<T> type, T service)
Registers a service.
- type
- the key type, usually an interface the service implements
- service
- the service instance
Throws IllegalStateException if a service is already registered for type or the registry is closed
public <T> Optional<T> find(Class<T> type)
Looks up a service.
- type
- key type
Returns the service, or empty if none is registered
public <T> T require(Class<T> type)
Looks up a service that must exist.
- type
- key type
Returns the service
Throws BloomException if no service is registered, with a message listing the registered services
public <T> T getOrRegister(Class<T> type, Supplier<? extends T> factory)
Returns the registered service, atomically creating and registering it first if absent.
- type
- key type
- factory
- creates the service; called at most once per type
Returns the existing or newly created service
public boolean isRegistered(Class<?> type)
Returns whether a service is registered.
- type
- key type
Returns true if registered
public Set<Class<?>> types()
Returns the registered key types in registration order.
Returns snapshot of registered types
io.github.crownalonedev.bloom.api.text
Placeholder class
public final class Placeholder
A {key} placeholder and the value that replaces it. Values created with of are inserted as plain text : formatting codes or tags inside the value are neutralised, so untrusted input such as player chat cannot inject colours or MiniMessage tags. Use formatted only for trusted values that intentionally contain formatting. messenger.send(player, "&dWelcome, {player}!", Placeholder.of("player", player.getName()));
Since 0.1.0
6 members
public static Placeholder of(String key, Object value)
Creates a plain-text placeholder. The value's toString() is used; null becomes "null".
- key
- key without braces, e.g. "player"
- value
- replacement value
Returns the placeholder
public static Placeholder formatted(String key, String value)
Creates a placeholder whose value is parsed with the message's format. Only use with trusted values.
- key
- key without braces
- value
- replacement containing formatting in the same TextFormat as the message
Returns the placeholder
public String key()
Returns the key without braces.
Returns key
public String value()
Returns the replacement value.
Returns value
public boolean isFormatted()
Returns whether the value is trusted formatted text rather than plain text.
Returns true if created with formatted
io.github.crownalonedev.bloom.api.text
TextFormat enum
public final enum TextFormat
The markup language used to write a message. Both formats work on every supported platform: • On modern Paper, MINIMESSAGE is parsed by the real MiniMessage library and LEGACY by Adventure's legacy serializer. • On legacy servers, LEGACY is native, and MINIMESSAGE is converted by Bloom's MiniMessage subset converter: named colours, hex colours (downsampled to the nearest legacy colour), decorations, <reset> and <newline>. Interactive tags (click, hover, insertion) and gradients are rendered as plain text content without their effect.
Since 0.1.0
4 members
public static TextFormat[] values()
public static TextFormat valueOf(String name)
- name
- String
LEGACY
Legacy colour codes with & (or §), e.g. "&dHello &lworld".
MINIMESSAGE
MiniMessage tags, e.g. "<light_purple>Hello <bold>world".
io.github.crownalonedev.bloom.api.util
Cooldowns class
public final class Cooldowns<K>
Thread-safe cooldown tracking keyed by any value, typically a player UUID. private final Cooldowns<UUID> pearl = Cooldowns.of(Duration.ofSeconds(15)); if (!pearl.tryUse(player.getUniqueId())) { player.sendMessage("Wait " + Durations.format(pearl.remaining(player.getUniqueId()))); return; } Expired entries are removed lazily when accessed and by prune. Cooldowns are kept in memory only.
Since 0.1.0
14 members
public static <K> Cooldowns<K> of(Duration defaultDuration)
Creates cooldowns with a default duration using the system clock.
- defaultDuration
- positive duration applied by tryUse and start
Returns a new cooldown tracker
public static <K> Cooldowns<K> of(Duration defaultDuration, Clock clock)
Creates cooldowns with a custom clock, mainly for tests.
- defaultDuration
- positive default duration
- clock
- time source
Returns a new cooldown tracker
public boolean tryUse(K key)
Starts the default cooldown if the key is not on cooldown.
- key
- key to use
Returns true if the key was free and the cooldown was started; false if still cooling down
public boolean tryUse(K key, Duration duration)
Starts a cooldown of a specific duration if the key is not on cooldown. Atomic per key.
- key
- key to use
- duration
- positive cooldown duration
Returns true if the cooldown was started
public void start(K key)
Starts (or restarts) the default cooldown unconditionally.
- key
- key
public void start(K key, Duration duration)
Starts (or restarts) a cooldown unconditionally.
- key
- key
- duration
- positive duration
public boolean isActive(K key)
Returns whether a key is cooling down.
- key
- key
Returns true if the cooldown has not expired
public Duration remaining(K key)
Returns the remaining cooldown time.
- key
- key
Returns remaining time, Duration.ZERO if not on cooldown
public Optional<Instant> expiry(K key)
Returns when the key's cooldown expires.
- key
- key
Returns expiry instant, or empty if not on cooldown
public void reset(K key)
Clears a key's cooldown.
- key
- key
public void clear()
Clears all cooldowns.
public int prune()
Removes expired entries. Call periodically if keys are rarely accessed again.
Returns number of removed entries
public int size()
Returns the number of tracked entries, including expired entries not yet pruned.
Returns entry count
public Duration defaultDuration()
Returns the default duration.
Returns default duration
io.github.crownalonedev.bloom.api.util
Durations class
public final class Durations
Parsing and formatting of human-friendly durations such as "1h30m" or "2d 4h". Supported units: ms, s, m, h, d, w. Months and years are not supported because their length varies.
Since 0.1.0
3 members
public static Duration parse(String text)
Parses a duration such as "90s", "1h30m", "2d 4h" or "500ms". A bare number is interpreted as seconds.
- text
- text to parse
Returns the duration
Throws IllegalArgumentException if the text is not a valid duration, with a message showing valid examples
public static String format(Duration duration)
Formats a duration compactly, e.g. "1h 5m 3s". Sub-second durations above zero format as "<1s"; zero formats as "0s".
- duration
- non-negative duration
Returns compact representation
public static String formatLong(Duration duration)
Formats a duration in words, e.g. "1 hour, 5 minutes and 3 seconds".
- duration
- non-negative duration
Returns long-form English representation
io.github.crownalonedev.bloom.api.util
ExpiringCache class
public final class ExpiringCache<K, V>
A small thread-safe cache with time-to-live expiry and a maximum size (least-recently-used eviction). Intended for modest caches such as recently looked-up player data. It uses a single lock, so it is not suitable for very hot, highly contended paths; for those use a dedicated caching library.
Since 0.1.0
9 members
public static <K, V> ExpiringCache<K,V> create(Duration ttl, int maxSize)
Creates a cache.
- ttl
- how long entries stay valid after being written
- maxSize
- maximum number of entries
Returns the cache
public static <K, V> ExpiringCache<K,V> create(Duration ttl, int maxSize, Clock clock)
Creates a cache with a custom clock, mainly for tests.
- ttl
- entry lifetime
- maxSize
- maximum number of entries
- clock
- time source
Returns the cache
public Optional<V> get(K key)
Returns a cached value if present and not expired.
- key
- key
Returns value, or empty
public V get(K key, Function<? super K,? extends V> loader)
Returns the cached value, computing and caching it when absent or expired. The loader runs while the cache lock is held, so it must be fast and must not access this cache.
- key
- key
- loader
- computes a missing value; must not return null
Returns cached or computed value
public void put(K key, V value)
Stores a value.
- key
- key
- value
- value, not null
public void invalidate(K key)
Removes a value.
- key
- key
public void clear()
Removes all values.
public int prune()
Removes expired entries.
Returns number of removed entries
public int size()
Returns the number of entries, including expired entries not yet pruned.
Returns size
bloom-bukkit
Bloom for Bukkit-family servers: Bloom entry point, platform detection, adapter SPI, scheduler, messaging and events.
io.github.crownalonedev.bloom.bukkit
Bloom class
public final class Bloom
The Bloom entry point for Bukkit-family plugins. public final class MyPlugin extends JavaPlugin { private Bloom bloom; @Override public void onEnable() { bloom = Bloom.enable(this); bloom.messages().send(getServer().getConsoleSender(), "&dBloom is ready on {platform}", Placeholder.of("platform", bloom.platform().describe())); } @Override public void onDisable() { if (bloom != null) { bloom.shutdown(); } } } enable detects the server, selects the matching version adapter, starts core services and logs a startup banner. If the server is not supported it throws BloomStartupException with an explanation; let it propagate from onEnable (the server then disables the plugin) or catch it to disable gracefully. In embedded mode each plugin has its own relocated copy of Bloom, so get returns the instance of the calling plugin.
Since 0.1.0
18 members
public static Bloom enable(Plugin plugin)
Starts Bloom for a plugin with default options. Call from onEnable().
- plugin
- the plugin that embeds Bloom
Returns the running instance
Throws BloomStartupException if the platform is unsupported or the adapter is missing
Throws IllegalStateException if Bloom is already running for this plugin
public static Bloom enable(Plugin plugin, BloomOptions options)
Starts Bloom for a plugin. Call from onEnable().
- plugin
- the plugin that embeds Bloom
- options
- startup options
Returns the running instance
Throws BloomStartupException if the platform is unsupported or the adapter is missing
Throws IllegalStateException if Bloom is already running for this plugin
public static Bloom get()
Returns the running instance.
Returns the instance created by enable
Throws IllegalStateException if Bloom is not running
public static Optional<Bloom> find()
Returns the running instance, if any.
Returns the instance, or empty if not running
public void shutdown()
Shuts Bloom down: closes feature services (open menus are closed, databases flushed), unregisters event subscriptions, cancels scheduled tasks and disables the adapter. Call from onDisable(). Idempotent.
public Plugin plugin()
Returns the owning plugin.
Returns plugin
public BloomOptions options()
Returns the options Bloom was started with.
Returns options
public LifecycleState state()
Returns the lifecycle state.
Returns state
public PlatformInfo platform()
Returns the detected platform.
Returns platform info
public Capabilities capabilities()
Returns the capabilities of the running platform.
Returns capabilities
public boolean has(Capability capability)
Shortcut for capabilities().has(capability).
- capability
- capability to check
Returns true if available
public PlatformAdapter adapter()
Returns the active version adapter. Advanced: intended for Bloom modules and diagnostics.
Returns adapter
public BloomScheduler scheduler()
Returns the task scheduler. Tasks are cancelled on shutdown.
Returns scheduler
public Messenger messages()
Returns the default messenger, using the text format from BloomOptions.
Returns messenger
public Events events()
Returns the event subscription service. Subscriptions are removed on shutdown.
Returns events
public ServiceRegistry services()
Returns the service registry. Feature modules register their services here on first use (for example Menus.of(bloom)); closeable services are closed on shutdown in reverse order.
Returns services
public <T> T service(Class<T> type)
Shortcut for services().require(type).
- type
- service key type
Returns the service
public boolean isUntestedPlatform()
Returns whether the server is newer than the supported range and Bloom only started because of BloomOptions.Builder.allowNewerUntestedVersions.
Returns true on an explicitly allowed untested version
io.github.crownalonedev.bloom.bukkit
BloomOptions class
public final class BloomOptions
Startup options for Bloom.enable. Bloom bloom = Bloom.enable(this, BloomOptions.builder() .textFormat(TextFormat.MINIMESSAGE) .unsupportedFeaturePolicy(UnsupportedFeaturePolicy.FALLBACK_TO_CHAT) .build());
Since 0.1.0
7 members
public static BloomOptions defaults()
Returns the default options.
Returns defaults: TextFormat.LEGACY, UnsupportedFeaturePolicy.SKIP, no untested versions, no debug, full startup banner
public static BloomOptions.Builder builder()
Creates a builder initialised with the defaults.
Returns a builder
public TextFormat textFormat()
Returns the default text format for bloom.messages() and item/menu text.
Returns text format
public UnsupportedFeaturePolicy unsupportedFeaturePolicy()
Returns the default policy for unsupported features.
Returns policy
public boolean allowNewerUntestedVersions()
Returns whether Bloom may start on Paper versions newer than the newest supported one.
Returns opt-in flag
public boolean debug()
Returns whether debug diagnostics are logged.
Returns debug flag
public boolean quietStartup()
Returns whether the startup banner is reduced to one line.
Returns quiet flag
io.github.crownalonedev.bloom.bukkit
BloomOptions.Builder class
public static final class Builder
Builder for BloomOptions.
6 members
public BloomOptions.Builder textFormat(TextFormat format)
Sets the default text format.
- format
- format used by bloom.messages() and builders that accept text
Returns this builder
public BloomOptions.Builder unsupportedFeaturePolicy(UnsupportedFeaturePolicy policy)
Sets the default unsupported-feature policy.
- policy
- policy
Returns this builder
public BloomOptions.Builder allowNewerUntestedVersions(boolean allow)
Allows starting on Paper versions newer than this Bloom release supports. Bloom logs a prominent warning. Use only if you test your plugin on that version yourself.
- allow
- opt-in flag
Returns this builder
public BloomOptions.Builder debug(boolean debug)
Enables debug diagnostics (adapter probe details, relocation details).
- debug
- flag
Returns this builder
public BloomOptions.Builder quietStartup(boolean quiet)
Reduces the startup banner to a single line.
- quiet
- flag
Returns this builder
public BloomOptions build()
Builds the options.
Returns immutable options
io.github.crownalonedev.bloom.bukkit
UnsupportedFeaturePolicy enum
public final enum UnsupportedFeaturePolicy
What Bloom does when code uses a feature the running platform lacks, such as action bars on 1.7.10.
Since 0.1.0
5 members
public static UnsupportedFeaturePolicy[] values()
public static UnsupportedFeaturePolicy valueOf(String name)
- name
- String
SKIP
Skip the operation and log one warning per feature. The method returns false. Default.
FALLBACK_TO_CHAT
Deliver text features (action bar, title) as a chat message instead; other features are skipped.
THROW
Throw UnsupportedCapabilityException.
io.github.crownalonedev.bloom.bukkit.event
Events class
public final class Events implements Terminable
Lambda-based event subscriptions that are automatically removed when Bloom shuts down. Events events = bloom.events(); events.subscribe(PlayerJoinEvent.class, event -> messages.send(event.getPlayer(), "&dWelcome!")); events.listen(PlayerInteractEvent.class) .priority(EventPriority.HIGH) .ignoreCancelled() .filter(event -> event.getItem() != null) .limit(1) .handler(event -> event.getPlayer().sendMessage("First interaction!")); Handlers run on the thread that fires the event: the main thread for most events, a background thread for asynchronous events such as AsyncPlayerPreLoginEvent. Exceptions thrown by handlers are reported by the server with the plugin's name, like any listener exception.
Since 0.1.0
7 members
public Events(Plugin plugin)
Creates the service. Internal: obtain it from bloom.events().
- plugin
- owning plugin
public <E extends Event> Subscription subscribe(Class<E> type, Consumer<? super E> handler)
Subscribes a handler at EventPriority.NORMAL, receiving cancelled events too.
- type
- concrete event class (must declare a HandlerList)
- handler
- handler
Returns the subscription
public <E extends Event> SubscriptionBuilder<E> listen(Class<E> type)
Starts building a subscription with priority, filters and limits.
- type
- concrete event class
Returns a builder; call SubscriptionBuilder.handler to register
public Subscription register(Listener listener)
Registers a classic Listener with @EventHandler methods, tied to Bloom's lifecycle.
- listener
- listener instance
Returns a subscription that unregisters the listener
public int activeCount()
Returns the number of active subscriptions created through this service.
Returns active count
public void close()
Unregisters every subscription. Idempotent.
public boolean isClosed()
io.github.crownalonedev.bloom.bukkit.event
Subscription interface
public interface Subscription extends Terminable
An active event registration. close is equivalent to unsubscribe.
Since 0.1.0
5 members
public void unsubscribe()
Stops receiving events. Idempotent and safe from any thread.
public boolean isActive()
Returns whether the subscription still receives events.
Returns true until unsubscribed
public long handledCount()
Returns how many events the handler has processed.
Returns handled event count
public default void close()
public default boolean isClosed()
io.github.crownalonedev.bloom.bukkit.event
SubscriptionBuilder class
public final class SubscriptionBuilder<E extends Event>
Configures an event subscription. Created by Events.listen.
Since 0.1.0
5 members
public SubscriptionBuilder<E> priority(EventPriority newPriority)
Sets the listener priority.
- newPriority
- priority (default EventPriority.NORMAL)
Returns this builder
public SubscriptionBuilder<E> ignoreCancelled()
Skips events that another listener already cancelled.
Returns this builder
public SubscriptionBuilder<E> filter(Predicate<? super E> predicate)
Only handles events that match a predicate. Multiple calls combine with logical AND.
- predicate
- condition
Returns this builder
public SubscriptionBuilder<E> limit(long maxCalls)
Unsubscribes automatically after the handler processed a number of (filtered) events.
- maxCalls
- positive number of calls
Returns this builder
public Subscription handler(Consumer<? super E> handler)
Registers the handler.
- handler
- event handler
Returns the active subscription
io.github.crownalonedev.bloom.bukkit.platform
AdapterContext class
public final class AdapterContext
Information passed to PlatformAdapter.enable.
Since 0.1.0
5 members
public AdapterContext(Plugin plugin, PlatformInfo platform, Logger logger, boolean debug)
Creates a context.
- plugin
- owning plugin
- platform
- detected platform
- logger
- plugin logger
- debug
- whether verbose diagnostics are enabled
public Plugin plugin()
Returns the owning plugin.
Returns plugin
public PlatformInfo platform()
Returns the detected platform.
Returns platform
public Logger logger()
Returns the plugin logger.
Returns logger
public boolean debug()
Returns whether debug diagnostics are enabled.
Returns debug flag
io.github.crownalonedev.bloom.bukkit.platform
AdapterLoader class
public final class AdapterLoader
Loads the adapter for a platform family by class name. The class name is derived from the runtime package of this class, so it stays correct when plugins relocate Bloom (e.g. to com.example.libs.bloom). Only the selected family's class is ever loaded, which keeps Java 21 adapter bytecode away from Java 8 servers.
Since 0.1.0
2 members
public static String adapterClassName(PlatformFamily family)
Returns the fully qualified adapter class name for a family, relative to Bloom's runtime root package.
- family
- platform family
Returns class name, e.g. io.github.crownalonedev.bloom.platform.modern.ModernPlatformAdapter
public static PlatformAdapter load(PlatformFamily family, PlatformInfo platform)
Loads and instantiates an adapter.
- family
- selected family
- platform
- detected platform, used in error messages
Returns a new adapter instance (not yet enabled)
Throws BloomStartupException if the adapter is missing or cannot be loaded, with a corrective message
io.github.crownalonedev.bloom.bukkit.platform
ItemPlatform interface
public interface ItemPlatform
Adapter SPI for item operations that differ between versions. SPI: plugin code should use bloom-items. Methods guarded by a capability are only called by Bloom when it is present.
Since 0.1.0
13 members
public Optional<ItemStack> create(String materialName, short data, int amount)
Creates an item from an exact material constant name of the running server.
- materialName
- exact Material constant name on this server, e.g. "RED_WOOL" (modern) or "WOOL" (legacy)
- data
- legacy data/durability value; must be 0 on platforms without LEGACY_DATA_VALUES
- amount
- stack size
Returns the item, or empty if the material does not exist on this server
public void displayName(ItemMeta meta, FormattedText name)
Sets the display name.
- meta
- item meta to modify
- name
- prepared name
public void lore(ItemMeta meta, List<FormattedText> lore)
Replaces the lore.
- meta
- item meta to modify
- lore
- prepared lore lines
public List<String> addItemFlags(ItemMeta meta, Collection<String> flagNames)
Adds item flags by Bukkit ItemFlag constant name. Requires ITEM_FLAGS.
- meta
- item meta to modify
- flagNames
- constant names, e.g. "HIDE_ENCHANTS"
Returns names that do not exist on this server and were skipped
public void unbreakable(ItemMeta meta, boolean unbreakable)
Sets the unbreakable flag. Requires UNBREAKABLE_ITEMS.
- meta
- item meta to modify
- unbreakable
- value
public void customModelData(ItemMeta meta, int value)
Sets custom model data. Requires CUSTOM_MODEL_DATA.
- meta
- item meta to modify
- value
- model data value
public void glow(ItemMeta meta)
Makes the item glow like an enchanted item without showing an enchantment. Modern servers use the native glint override; legacy servers add a hidden enchantment (visible on 1.7.10, which lacks item flags).
- meta
- item meta to modify
public Optional<Enchantment> enchantment(String name)
Resolves an enchantment by modern key ("sharpness", "minecraft:sharpness") or legacy Bukkit name ("DAMAGE_ALL").
- name
- enchantment key or name, case-insensitive
Returns the enchantment, or empty if unknown on this server
public ItemStack writeData(ItemStack item, String namespace, String key, String value)
Writes a string value into the item's persistent data. Requires PERSISTENT_DATA_CONTAINER or ITEM_NBT_TAGS.
- item
- source item (not modified)
- namespace
- owning namespace, lowercase plugin name
- key
- key within the namespace, [a-z0-9._-]+
- value
- value to store
Returns a copy of the item carrying the value
public Optional<String> readData(ItemStack item, String namespace, String key)
Reads a string value from the item's persistent data.
- item
- item to read
- namespace
- owning namespace
- key
- key within the namespace
Returns the value, or empty if absent
public ItemStack removeData(ItemStack item, String namespace, String key)
Removes a value from the item's persistent data.
- item
- source item (not modified)
- namespace
- owning namespace
- key
- key within the namespace
Returns a copy of the item without the value
public String serialize(ItemStack item)
Serialises an item to a portable string for storage on the same platform family.
- item
- item to serialise
Returns serialised form with a format prefix
public ItemStack deserialize(String data)
Deserialises an item produced by serialize on the same platform family.
- data
- serialised form
Returns the item
Throws IllegalArgumentException if the data is malformed or from another family
io.github.crownalonedev.bloom.bukkit.platform
PlatformAdapter interface
public interface PlatformAdapter
A version adapter: the only place where version-specific Bukkit/Paper/NMS behaviour lives. SPI: implemented by bloom-legacy and bloom-modern; not intended for plugin code. Implementations must have a public no-argument constructor and must not touch server state in it. Bloom loads an adapter class by name only after SupportPolicy selected its family, so classes of other adapters are never loaded.
Since 0.1.0
7 members
public PlatformFamily family()
Returns the family this adapter serves.
Returns platform family
public String description()
Returns a short description for logs, e.g. "legacy (Bukkit 1.7.10-1.8.9)".
Returns description
public Capabilities enable(AdapterContext context)
Initialises the adapter and probes optional features. Called once on the main thread.
- context
- startup context
Returns capabilities available on this server
public void disable()
Releases adapter resources. Called once during Bloom shutdown, on the main thread.
public TextPlatform text()
Returns text rendering and delivery.
Returns text platform
public PlayerPlatform players()
Returns player and inventory operations.
Returns player platform
public ItemPlatform items()
Returns item operations.
Returns item platform
io.github.crownalonedev.bloom.bukkit.platform
PlatformDetector class
public final class PlatformDetector
Detects the server implementation and Minecraft version from what the server reports. Implementation detection uses class probes (without initialising classes) rather than the server name alone, because forks often report custom names.
Since 0.1.0
3 members
public static PlatformInfo detect(Server server)
Detects the platform of a running server.
- server
- the server
Returns platform description
Throws BloomStartupException if the Minecraft version cannot be determined
public static PlatformInfo detect(String serverName, String serverVersion, String bukkitVersion, String serverClassName, PlatformDetector.ClassProbe probe, JavaRuntime java)
Detects a platform from raw values.
- serverName
- Server#getName()
- serverVersion
- Server#getVersion()
- bukkitVersion
- Server#getBukkitVersion()
- serverClassName
- runtime class name of the Server implementation
- probe
- class presence probe
- java
- Java runtime
Returns platform description
Throws BloomStartupException if the Minecraft version cannot be determined
public static ServerSoftware detectSoftware(String serverName, String serverClassName, PlatformDetector.ClassProbe probe)
Identifies the server implementation.
- serverName
- Server#getName()
- serverClassName
- runtime class name of the server implementation
- probe
- class presence probe
Returns the implementation
io.github.crownalonedev.bloom.bukkit.platform
PlatformDetector.ClassProbe interface
public static interface ClassProbe
Probe for class presence; abstracted so detection logic is unit-testable without a server.
1 member
public boolean exists(String className)
Tests whether a class exists.
- className
- fully qualified class name
Returns true if loadable
io.github.crownalonedev.bloom.bukkit.platform
PlayerPlatform interface
public interface PlayerPlatform
Adapter SPI for player and inventory operations whose binary signatures differ between server versions. Examples: Bukkit.getOnlinePlayers() returns an array on 1.7.10 and a collection on 1.8+; InventoryView is a class before 1.21 and an interface after, so calling its methods from shared code would fail with IncompatibleClassChangeError.
Since 0.1.0
4 members
public Collection<? extends Player> onlinePlayers()
Returns the online players.
Returns snapshot of online players
public Inventory openTopInventory(Player player)
Returns the top inventory of the player's open inventory view.
- player
- player
Returns top inventory (the player's crafting inventory when no container is open)
public InventoryHolder holder(Inventory inventory)
Returns an inventory's holder as cheaply as possible. On Paper this avoids creating block-state snapshots, which matters because menu listeners inspect every inventory click on the server.
- inventory
- inventory
Returns holder, or null
public Inventory createInventory(InventoryHolder holder, int size, FormattedText title)
Creates a chest inventory.
- holder
- holder identifying the inventory
- size
- slot count, a multiple of 9 between 9 and 54
- title
- prepared title; legacy adapters truncate to 32 characters
Returns the inventory
io.github.crownalonedev.bloom.bukkit.platform
TextPlatform interface
public interface TextPlatform
Adapter SPI for rendering and delivering text. Implemented by each platform adapter. SPI: plugin code should use Messenger. Methods guarded by a capability are only called by Bloom when that capability is present.
Since 0.1.0
5 members
public void sendMessage(CommandSender target, FormattedText text)
Sends a chat message.
- target
- recipient (player or console)
- text
- prepared text
public void sendActionBar(Player player, FormattedText text)
Sends an action bar message. Requires ACTION_BAR.
- player
- recipient
- text
- prepared text
public void sendTitle(Player player, FormattedText title, FormattedText subtitle, Duration fadeIn, Duration stay, Duration fadeOut)
Shows a title. Requires TITLES; timings are honoured only with TITLE_TIMINGS.
- player
- recipient
- title
- prepared title
- subtitle
- prepared subtitle
- fadeIn
- fade-in
- stay
- stay
- fadeOut
- fade-out
public BloomBossBar createBossBar(FormattedText title, float progress, BossBarColor color, BossBarStyle style, TextPlatform.TitleRenderer renderer)
Creates a boss bar. Requires BOSS_BAR.
- title
- prepared title
- progress
- progress 0..1
- color
- colour
- style
- style
- renderer
- renders later title updates given as templates in the messenger's format
Returns a functional boss bar
public String toLegacyString(FormattedText text)
Renders text to a legacy § string, e.g. for APIs that only accept strings.
- text
- prepared text
Returns legacy formatted string
io.github.crownalonedev.bloom.bukkit.platform
TextPlatform.TitleRenderer interface
public static interface TitleRenderer
Converts a title template into prepared text using the owning messenger's settings.
1 member
public FormattedText render(String template)
Prepares a template.
- template
- template text
Returns prepared text
io.github.crownalonedev.bloom.bukkit.text
BloomBossBar interface
public interface BloomBossBar extends Terminable
A boss bar shown to a set of players. Created by Messenger.bossBar. Must be used from the main thread. Closing the bar hides it from all viewers; Bloom closes open bars on shutdown. On platforms without Capability.BOSS_BAR (with the SKIP policy) a no-op bar is returned whose isFunctional is false.
Since 0.1.0
8 members
public BloomBossBar title(String title)
Sets the title.
- title
- title in the owning messenger's format
Returns this bar
public BloomBossBar progress(float progress)
Sets the progress.
- progress
- value between 0.0 and 1.0
Returns this bar
Throws IllegalArgumentException if out of range
public BloomBossBar color(BossBarColor color)
Sets the colour.
- color
- colour
Returns this bar
public BloomBossBar style(BossBarStyle style)
Sets the style.
- style
- style
Returns this bar
public BloomBossBar show(Player player)
Shows the bar to a player.
- player
- viewer to add
Returns this bar
public BloomBossBar hide(Player player)
Hides the bar from a player.
- player
- viewer to remove
Returns this bar
public Collection<UUID> viewers()
Returns the current viewers.
Returns snapshot of viewer UUIDs
public boolean isFunctional()
Returns whether this bar actually renders on the current platform.
Returns false for the no-op fallback bar
io.github.crownalonedev.bloom.bukkit.text
BossBarColor enum
public final enum BossBarColor
Boss bar colours. Mapped to the platform's boss bar API by the adapter.
Since 0.1.0
9 members
public static BossBarColor[] values()
public static BossBarColor valueOf(String name)
- name
- String
io.github.crownalonedev.bloom.bukkit.text
BossBarStyle enum
public final enum BossBarStyle
Boss bar segment styles.
Since 0.1.0
7 members
public static BossBarStyle[] values()
public static BossBarStyle valueOf(String name)
- name
- String
SEGMENTED_10
Ten segments.
SEGMENTED_12
Twelve segments.
SEGMENTED_20
Twenty segments.
io.github.crownalonedev.bloom.bukkit.text
FormattedText class
public final class FormattedText
Text whose placeholders have been applied and which is ready for an adapter to render. For TextFormat.MINIMESSAGE, content is MiniMessage markup. For TextFormat.LEGACY, it is a §-formatted string (& codes already translated). Plugin code normally never creates this directly; Messenger and the item/menu builders do.
Since 0.1.0
6 members
public static FormattedText prepare(String template, TextFormat format, boolean hexSupported, Placeholder... placeholders)
Applies placeholders to a template.
- template
- message template in format
- format
- template format
- hexSupported
- whether &#RRGGBB may produce real RGB colours
- placeholders
- placeholder values
Returns prepared text
public static FormattedText ofPrepared(String content, TextFormat format)
Wraps already-prepared content.
- content
- prepared content (MiniMessage markup or § string)
- format
- format of content
Returns text
public String content()
Returns the prepared content.
Returns MiniMessage markup or a §-formatted string, depending on format
public TextFormat format()
Returns the content format.
Returns format
public boolean isEmpty()
Returns whether the content is empty.
Returns true if empty
io.github.crownalonedev.bloom.bukkit.text
Messenger class
public final class Messenger
Sends formatted text to players and the console on every supported platform. Obtain the default instance with bloom.messages(); derive variants with withPrefix, withFormat and withUnsupportedPolicy. Messengers are immutable and thread-safe. Messenger messages = bloom.messages().withPrefix("&d&lBloom &8» "); messages.send(player, "&7Welcome back, &f{player}&7!", Placeholder.of("player", player.getName())); messages.actionBar(player, "&aSaved!"); messages.title(player, Title.of("&dLevel up", "&7You reached level {level}"), Placeholder.of("level", 5)); Threads Chat, action bars and titles may be sent from any thread. Boss bars must be created and changed on the main thread. Unsupported features Action bars, titles and boss bars depend on capabilities. When one is missing, behaviour follows the UnsupportedFeaturePolicy: skip with a one-time warning (default), fall back to chat, or throw.
Since 0.1.0
15 members
public Messenger(TextPlatform text, PlayerPlatform players, Capabilities capabilities, Logger logger, Consumer<AutoCloseable> closeOnShutdown, TextFormat format, UnsupportedFeaturePolicy policy)
Creates a messenger. Internal: plugin code obtains messengers from bloom.messages().
- text
- adapter text platform
- players
- adapter player platform
- capabilities
- platform capabilities
- logger
- plugin logger
- closeOnShutdown
- registers boss bars so they are closed at shutdown
- format
- default format
- policy
- default unsupported-feature policy
public TextFormat format()
Returns the text format this messenger parses templates with.
Returns format
public String prefix()
Returns the chat prefix template.
Returns prefix, empty if none
public UnsupportedFeaturePolicy unsupportedPolicy()
Returns the unsupported-feature policy.
Returns policy
public Messenger withFormat(TextFormat newFormat)
Returns a messenger that parses templates in another format.
- newFormat
- format
Returns derived messenger
public Messenger withPrefix(String newPrefix)
Returns a messenger that prepends a prefix to chat messages (not to action bars, titles or boss bars). The prefix is written in this messenger's format.
- newPrefix
- prefix template, e.g. "&d[Shop] "
Returns derived messenger
public Messenger withUnsupportedPolicy(UnsupportedFeaturePolicy newPolicy)
Returns a messenger with another unsupported-feature policy.
- newPolicy
- policy
Returns derived messenger
public FormattedText render(String template, Placeholder... placeholders)
Applies placeholders to a template using this messenger's format.
- template
- template text
- placeholders
- placeholders
Returns prepared text for adapter APIs
public String legacy(String template, Placeholder... placeholders)
Renders a template to a legacy §-formatted string, for APIs that only accept strings (scoreboards, signs on old versions).
- template
- template text
- placeholders
- placeholders
Returns legacy string
public void send(CommandSender recipient, String message, Placeholder... placeholders)
Sends a chat message with this messenger's prefix.
- recipient
- player or console
- message
- message template
- placeholders
- placeholder values
public void send(Iterable<? extends CommandSender> recipients, String message, Placeholder... placeholders)
Sends a chat message to several recipients. The template is rendered once.
- recipients
- players or console
- message
- message template
- placeholders
- placeholder values
public void broadcast(String message, Placeholder... placeholders)
Sends a chat message to every online player and the console.
- message
- message template
- placeholders
- placeholder values
public boolean actionBar(Player player, String message, Placeholder... placeholders)
Shows an action bar message.
- player
- recipient
- message
- message template (no prefix is added)
- placeholders
- placeholder values
Returns true if delivered as an action bar or as a chat fallback
Throws UnsupportedCapabilityException if unsupported and the policy is THROW
public boolean title(Player player, Title title, Placeholder... placeholders)
Shows a title.
- player
- recipient
- title
- title and subtitle templates with timings
- placeholders
- placeholder values, applied to both lines
Returns true if delivered as a title or as a chat fallback
Throws UnsupportedCapabilityException if unsupported and the policy is THROW
public BloomBossBar bossBar(String title, float progress, BossBarColor color, BossBarStyle style, Placeholder... placeholders)
Creates a boss bar. Show it to players with BloomBossBar.show. Must be called on the main thread. Bloom closes the bar on shutdown.
- title
- title template
- progress
- progress between 0 and 1
- color
- colour
- style
- style
- placeholders
- placeholder values for the initial title
Returns a boss bar, or a non-functional bar (BloomBossBar.isFunctional is false) when boss bars are unsupported and the policy is not THROW
Throws UnsupportedCapabilityException if unsupported and the policy is THROW
io.github.crownalonedev.bloom.bukkit.text
Title class
public final class Title
A title/subtitle pair with display timings. Timings require Capability.TITLE_TIMINGS; on 1.8 servers the client's default timings are used (fade in 0.5s, stay 3.5s, fade out 1s) and custom timings are ignored. messenger.title(player, Title.of("&dWelcome", "&7to the server")); messenger.title(player, Title.of("<gold>Victory").times(Duration.ofMillis(250), Duration.ofSeconds(2), Duration.ofMillis(500)));
Since 0.1.0
11 members
public static final Duration DEFAULT_FADE_IN
Default fade-in time, matching the vanilla client.
public static final Duration DEFAULT_STAY
Default stay time, matching the vanilla client.
public static final Duration DEFAULT_FADE_OUT
Default fade-out time, matching the vanilla client.
public static Title of(String title)
Creates a title without a subtitle and with default timings.
- title
- title text in the messenger's format
Returns the title
public static Title of(String title, String subtitle)
Creates a title with a subtitle and default timings.
- title
- title text in the messenger's format
- subtitle
- subtitle text in the messenger's format
Returns the title
public Title times(Duration fadeIn, Duration stay, Duration fadeOut)
Returns a copy with custom timings.
- fadeIn
- fade-in duration
- stay
- stay duration
- fadeOut
- fade-out duration
Returns a new title
public String title()
Returns the title template.
Returns title text
public String subtitle()
Returns the subtitle template.
Returns subtitle text, possibly empty
public Duration fadeIn()
Returns the fade-in duration.
Returns fade-in
public Duration stay()
Returns the stay duration.
Returns stay
public Duration fadeOut()
Returns the fade-out duration.
Returns fade-out
bloom-items
Bloom Items: item builder, cross-version materials, persistent item identity and serialization.
io.github.crownalonedev.bloom.items
CustomItem class
public final class CustomItem
A custom item defined with Items.define.
Since 0.1.0
5 members
public String id()
Returns the custom id.
Returns id
public ItemStack create()
Creates one item.
Returns a new stack of size 1
public ItemStack create(int amount)
Creates a stack.
- amount
- stack size, >= 1
Returns a new stack
public boolean matches(ItemStack item)
Returns whether an item is an instance of this custom item, by persistent id (not by name or lore).
- item
- item, may be null
Returns true if the item carries this id
io.github.crownalonedev.bloom.items
ItemBuilder class
public final class ItemBuilder
Fluent, cross-version item builder. Created by Items.builder or Items.edit. Text (name, lore) uses the Bloom default TextFormat unless format is called, and renders white and non-italic unless the text sets its own colour. Features missing on the running server (e.g. custom model data on 1.8) follow the Bloom UnsupportedFeaturePolicy: skipped with a one-time warning by default. Builders are not thread-safe; build may be called repeatedly and returns a new item each time.
Since 0.1.0
17 members
public ItemBuilder amount(int newAmount)
Sets the stack size.
- newAmount
- amount, 1..64 (or the item's max stack size)
Returns this builder
public ItemBuilder name(String template)
Sets the display name.
- template
- name in the builder's text format, e.g. "&dBlossom Blade"
Returns this builder
public ItemBuilder lore(String... lines)
Replaces the lore.
- lines
- lore lines in the builder's text format
Returns this builder
public ItemBuilder lore(List<String> lines)
Replaces the lore.
- lines
- lore lines in the builder's text format
Returns this builder
public ItemBuilder addLore(String... lines)
Appends lore lines.
- lines
- lines to append
Returns this builder
public ItemBuilder enchant(String enchantment, int level)
Adds an enchantment by name. Accepts modern keys ("sharpness") and legacy Bukkit names ("DAMAGE_ALL"). Enchantments unknown on this server are skipped with a warning. Levels above the vanilla maximum are allowed.
- enchantment
- enchantment key or name
- level
- level, >= 1
Returns this builder
public ItemBuilder enchant(Enchantment enchantment, int level)
Adds an enchantment object from the API you compile against.
- enchantment
- enchantment
- level
- level, >= 1
Returns this builder
public ItemBuilder flags(ItemFlagKey... newFlags)
Adds item flags. Requires ITEM_FLAGS (1.8+).
- newFlags
- flags
Returns this builder
public ItemBuilder glow()
Makes the item glow without visible enchantments (see ItemPlatform#glow).
Returns this builder
public ItemBuilder unbreakable(boolean value)
Sets the unbreakable flag. Requires UNBREAKABLE_ITEMS.
- value
- unbreakable
Returns this builder
public ItemBuilder customModelData(int value)
Sets custom model data. Requires CUSTOM_MODEL_DATA (modern only).
- value
- model data
Returns this builder
public ItemBuilder data(String key, String value)
Stores a string in the item's persistent data under the plugin namespace.
- key
- key, [a-z0-9._-]+
- value
- value
Returns this builder
public ItemBuilder customId(String id)
Marks the item with a custom id (see Items.customId).
- id
- custom id
Returns this builder
public ItemBuilder placeholders(Placeholder... values)
Sets placeholders applied to the name and lore.
- values
- placeholders
Returns this builder
public ItemBuilder format(TextFormat textFormat)
Sets the text format for name and lore.
- textFormat
- format
Returns this builder
public ItemBuilder meta(Consumer<ItemMeta> editor)
Applies a custom edit to the Bukkit ItemMeta after Bloom's own settings. Use for features Bloom does not wrap (leather colour, skull owner, ...). Code here must be valid for every server version you target.
- editor
- meta editor
Returns this builder
public ItemStack build()
Builds a new item.
Returns the item
io.github.crownalonedev.bloom.items
ItemFlagKey enum
public final enum ItemFlagKey
Cross-version item flags. Each key maps to the Bukkit ItemFlag constant(s) that implement it on different versions; flags that do not exist on the running server are skipped. Requires Capability.ITEM_FLAGS (1.8+).
Since 0.1.0
12 members
public static ItemFlagKey[] values()
public static ItemFlagKey valueOf(String name)
- name
- String
HIDE_ENCHANTS
Hides enchantments.
HIDE_ATTRIBUTES
Hides attribute modifiers such as attack damage.
HIDE_UNBREAKABLE
Hides the "Unbreakable" line.
HIDE_DESTROYS
Hides "Can destroy" lines.
HIDE_PLACED_ON
Hides "Can be placed on" lines.
HIDE_ADDITIONAL_TOOLTIP
Hides potion effects and other additional tooltip lines (1.8 HIDE_POTION_EFFECTS, modern HIDE_ADDITIONAL_TOOLTIP).
HIDE_DYE
Hides leather armour dye colour (modern only).
HIDE_ARMOR_TRIM
Hides armour trims (modern only).
HIDE_STORED_ENCHANTS
Hides stored enchantments on enchanted books (modern only).
public List<String> bukkitNames()
Returns the Bukkit ItemFlag names that implement this flag, newest first.
Returns candidate constant names
io.github.crownalonedev.bloom.items
Items class
public final class Items
Cross-version item creation, identification and serialization. Items items = Items.of(bloom); ItemStack sword = items.builder("DIAMOND_SWORD") .name("&dBlossom Blade") .lore("&7Forged under falling petals.") .enchant("sharpness", 3) .flags(ItemFlagKey.HIDE_ENCHANTS) .unbreakable(true) .build(); CustomItem ruby = items.define("ruby", items.builder("RED_DYE").name("&cRuby").glow()); player.getInventory().addItem(ruby.create(3)); boolean isRuby = ruby.matches(player.getItemInHand()); Identity Custom ids and data are stored as namespaced persistent data, never in names or lore: PersistentDataContainer on modern servers, NBT on legacy servers. The namespace is the owning plugin's lowercase name. Data written on one platform family cannot be read on the other.
Since 0.1.0
22 members
public static final String ID_KEY
Data key used for custom item ids.
public static Items of(Bloom bloom)
Returns the items service of a Bloom instance, creating it on first use.
- bloom
- running Bloom instance
Returns the service
public ItemBuilder builder(String materialKey)
Starts building an item.
- materialKey
- modern material name (legacy names and NAME:DATA accepted); see MaterialMappings
Returns a builder
Throws IllegalArgumentException if the material does not exist on this server
public ItemBuilder builder(Material material)
Starts building from a Bukkit material constant of the API you compile against.
- material
- material
Returns a builder
public ItemBuilder edit(ItemStack item)
Starts editing a copy of an existing item. Name and lore are kept unless the builder sets them.
- item
- item to copy
Returns a builder
public Optional<ItemStack> create(String materialKey, int amount)
Creates a plain item.
- materialKey
- material key
- amount
- stack size
Returns the item, or empty if the material does not exist on this server
public boolean exists(String materialKey)
Returns whether a material key resolves on this server.
- materialKey
- material key
Returns true if create would succeed
public MaterialMappings materials()
Returns the material mappings, where custom keys can be registered.
Returns mappings
public String namespace()
Returns the persistent data namespace (lowercase plugin name).
Returns namespace
public boolean supportsData()
Returns whether items can carry persistent data on this server.
Returns true with PersistentDataContainer (modern) or NBT access (legacy)
public ItemStack setData(ItemStack item, String key, String value)
Returns a copy of an item with a string value stored under this plugin's namespace.
- item
- source item (unchanged)
- key
- key, [a-z0-9._-]+
- value
- value
Returns tagged copy
Throws UnsupportedCapabilityException if items cannot carry data on this server
public Optional<String> getData(ItemStack item, String key)
Reads a value stored by setData.
- item
- item, may be null
- key
- key
Returns the value, or empty
public ItemStack removeData(ItemStack item, String key)
Returns a copy of an item without a stored value.
- item
- source item (unchanged)
- key
- key
Returns copy without the key
public ItemStack tag(ItemStack item, String id)
Returns a copy of an item marked with a custom id.
- item
- source item
- id
- custom id, [a-z0-9._-]+
Returns tagged copy
public Optional<String> customId(ItemStack item)
Returns the custom id of an item.
- item
- item, may be null
Returns id, or empty if the item has none
public boolean isCustom(ItemStack item, String id)
Returns whether an item carries a custom id.
- item
- item, may be null
- id
- expected id
Returns true if the ids match
public CustomItem define(String id, ItemBuilder template)
Defines a custom item. The template is built once and tagged with the id; CustomItem.create returns copies.
- id
- unique id, [a-z0-9._-]+
- template
- builder describing the item
Returns the definition
Throws IllegalStateException if the id is already defined
public Optional<CustomItem> custom(String id)
Looks up a custom item definition.
- id
- custom id
Returns the definition, or empty
public Optional<CustomItem> match(ItemStack item)
Finds the custom item definition an item stack belongs to.
- item
- item, may be null
Returns the definition, or empty for plain items and unknown ids
public Collection<CustomItem> customItems()
Returns all custom item definitions.
Returns snapshot in definition order
public String serialize(ItemStack item)
Serialises an item to a string for storage (databases, configs). The format is platform-family specific.
- item
- non-empty item
Returns serialised item
public ItemStack deserialize(String data)
Deserialises an item created by serialize on the same platform family.
- data
- serialised item
Returns the item
Throws IllegalArgumentException if malformed or from the other platform family
io.github.crownalonedev.bloom.items
MaterialMappings class
public final class MaterialMappings
Resolves Bloom material keys to the material names of the running server. Keys are modern (1.13+) material names , e.g. RED_WOOL, PLAYER_HEAD, OAK_PLANKS. Legacy names (WATCH) and legacy NAME:DATA specs (WOOL:14) are accepted too. Resolution order: • legacy servers: developer mapping → built-in modern→legacy table → the key itself → NAME:DATA • modern servers: developer mapping → the key itself → built-in legacy→modern table So an ambiguous name such as MELON always means the modern item (the block) on every server. Thread-safe.
Since 0.1.0
3 members
public MaterialMappings register(String key, String modernName, String legacyName, int legacyData)
Registers or replaces a mapping for a key.
- key
- Bloom key used in code/configs, e.g. "SHOP_ICON" or a modern material name
- modernName
- material name on modern servers, or null if not available there
- legacyName
- material name on legacy servers, or null if not available there
- legacyData
- legacy data value
Returns this instance
public List<MaterialMappings.Candidate> candidates(String key, boolean legacyPlatform)
Returns the names to try, in order, for a key on the given platform family.
- key
- material key
- legacyPlatform
- whether the server uses legacy data values
Returns ordered, de-duplicated candidates (never empty)
public static int builtinSize()
Returns the number of built-in table rows (for diagnostics).
Returns number of built-in modern→legacy mappings
io.github.crownalonedev.bloom.items
MaterialMappings.Candidate class
public static final class Candidate
A concrete material name and legacy data value to try on the running server.
5 members
public String name()
Returns the server material name.
Returns material constant name
public short data()
Returns the legacy data value.
Returns data value, 0 on modern servers
public boolean equals(Object o)
- o
- Object
bloom-gui
Bloom GUI: inventory menus with buttons, layouts, pagination, navigation and duplication-safe event handling.
io.github.crownalonedev.bloom.gui
Button class
public final class Button
An item in a menu slot with an optional click handler. Buttons are immutable; the with*/on* methods return modified copies, so one button can be reused in many menus. Button heal = Button.of(items.builder("GOLDEN_APPLE").name("&aHeal").build()) .permission("shop.heal") .onClick(click -> { click.player().setHealth(20.0); click.close(); }); Button counter = Button.dynamic(view -> items.builder("PAPER") .name("&fClicks: " + view.state().getOrDefault(CLICKS, 0)).build()) .onClick(click -> { click.view().state().set(CLICKS, click.view().state().getOrDefault(CLICKS, 0) + 1); click.refresh(); });
Since 0.1.0
7 members
public static Button of(ItemStack item)
Creates a button with a fixed item and no click action (a decoration).
- item
- item to display (copied when rendered)
Returns the button
public static Button of(ItemStack item, Consumer<ClickContext> onClick)
Creates a button with a fixed item and a click action.
- item
- item to display
- onClick
- click handler, runs on the main thread
Returns the button
public static Button dynamic(Function<MenuView,ItemStack> icon)
Creates a button whose item is computed for each viewer on every render (open, refresh, page change).
- icon
- computes the item; may return null for an empty slot
Returns the button
public Button onClick(Consumer<ClickContext> onClick)
Returns a copy with a click handler. Handlers run on the main thread; exceptions are logged and do not break the menu.
- onClick
- click handler
Returns a new button
public Button visibleWhen(Predicate<MenuView> condition)
Returns a copy that is only shown when a condition holds (evaluated on each render). Hidden buttons leave the slot to the menu's filler.
- condition
- visibility condition
Returns a new button
public Button permission(String node)
Returns a copy that is hidden from players without a permission.
- node
- permission node
Returns a new button
public Button permission(String node, ItemStack deniedItem)
Returns a copy that shows deniedItem (without running the click handler) to players lacking a permission.
- node
- permission node
- deniedItem
- item shown instead
Returns a new button
io.github.crownalonedev.bloom.gui
ClickContext class
public final class ClickContext
Information about a button click, passed to Button.onClick handlers. The underlying Bukkit event is always cancelled; items never move in or out of a Bloom menu. Navigation methods (open, back, close) take effect on the next tick, because opening or closing inventories inside a click event is unsafe on Bukkit servers.
Since 0.1.0
11 members
public Player player()
Returns the clicking player.
Returns player
public MenuView view()
Returns the player's view of the menu (page, state).
Returns view
public Menu menu()
Returns the menu definition.
Returns menu
public int slot()
Returns the clicked slot.
Returns slot index in the menu
public ClickKind kind()
Returns the kind of click.
Returns click kind
public int hotbarButton()
Returns the number key pressed for ClickKind.NUMBER_KEY clicks.
Returns hotbar slot 0-8, or -1
public Menus menus()
Returns the menu service.
Returns menus
public void refresh()
Re-renders the current menu for this player.
public void open(Menu menu)
Opens another menu on the next tick. The current menu is kept in the history for back.
- menu
- menu to open
public boolean back()
Goes back to the previous menu on the next tick.
Returns true if there is a previous menu
public void close()
Closes the menu on the next tick.
io.github.crownalonedev.bloom.gui
ClickKind enum
public final enum ClickKind
Version-independent click types. Mapped from Bukkit's ClickType by name, so constants added in newer versions never cause linkage errors on older servers.
Since 0.1.0
15 members
public static ClickKind[] values()
public static ClickKind valueOf(String name)
- name
- String
SHIFT_LEFT
Shift + left click.
SHIFT_RIGHT
Shift + right click.
MIDDLE
Middle click (creative pick).
NUMBER_KEY
Number key 1-9; see ClickContext.hotbarButton.
CONTROL_DROP
Control + drop key.
SWAP_OFFHAND
Off-hand swap key (F), 1.16+.
OTHER
Any other click (creative, window border, unknown).
public boolean isLeft()
Returns whether this is a left click (with or without shift).
Returns true for LEFT and SHIFT_LEFT
public boolean isRight()
Returns whether this is a right click (with or without shift).
Returns true for RIGHT and SHIFT_RIGHT
public boolean isShift()
Returns whether shift was held.
Returns true for shift clicks
io.github.crownalonedev.bloom.gui
StateKey class
public final class StateKey<T>
A typed key for per-player menu state. static final StateKey<Integer> QUANTITY = StateKey.of("quantity", Integer.class); int quantity = view.state().getOrDefault(QUANTITY, 1); view.state().set(QUANTITY, quantity + 1);
Since 0.1.0
4 members
public static <T> StateKey<T> of(String name, Class<T> type)
Creates a key. Keys are compared by identity, so declare them as constants.
- name
- descriptive name used in toString()
- type
- value type
Returns a new key
public String name()
Returns the key name.
Returns name
public Class<T> type()
Returns the value type.
Returns type
bloom-config
Bloom Config: YAML configuration with defaults, validation, object mapping, comment-preserving saves and migrations.
io.github.crownalonedev.bloom.config
ConfigException class
public class ConfigException extends BloomException
Thrown for configuration problems: unreadable YAML, missing or mistyped values, failed validation or migration. Messages name the file, the key path and, when known, the line number.
Since 0.1.0
4 members
public ConfigException(String message)
Creates an exception with one problem.
- message
- description including file/path/line
public ConfigException(String message, Throwable cause)
Creates an exception with a cause.
- message
- description
- cause
- cause
public ConfigException(String summary, List<String> problems)
Creates an exception listing several problems (validation).
- summary
- first line of the message
- problems
- individual problems
public List<String> problems()
Returns the individual problems.
Returns problems, at least one
io.github.crownalonedev.bloom.config
ConfigKey annotation
public abstract @interface ConfigKey implements Annotation
Overrides the YAML key of a mapped field. Without it, field names are converted from camelCase to kebab-case (maxHomes → max-homes).
Since 0.1.0
1 member
public abstract String value()
Returns the YAML key.
Returns key
io.github.crownalonedev.bloom.config
ConfigMigration interface
public interface ConfigMigration
Upgrades a configuration from one version to the next. Registered with YamlConfig.Builder.migration. YamlConfig config = YamlConfig.builder(file) .defaults(() -> plugin.getResource("config.yml")) .version(3) .migration(1, m -> m.move("prefix", "messages.prefix")) // v1 -> v2 .migration(2, m -> m.set("storage.type", m.has("mysql") ? "mysql" : "sqlite")) // v2 -> v3 .build();
Since 0.1.0
1 member
public void migrate(MigrationContext context)
Applies the migration to the configuration values.
- context
- mutable view of the values being migrated
io.github.crownalonedev.bloom.config
ConfigSection class
public class ConfigSection
Typed, path-based access to a section of a YamlConfig. Paths are dot-separated ("database.host") and relative to this section. Defaults A value missing from the file falls back to the bundled defaults. Required getters (getString(path)) throw ConfigException when the value is missing in both; getters with a fallback argument return the fallback. Errors Type mismatches throw ConfigException naming the file, path, line and the expected type, e.g. config.yml line 7: 'limits.homes' expected a whole number but found 'ten'. All methods are thread-safe.
Since 0.1.0
26 members
public String path()
Returns this section's path from the root.
Returns path, empty for the root
public boolean has(String path)
Returns whether a value exists in the file or the defaults.
- path
- relative path
Returns true if present
public boolean isSet(String path)
Returns whether a value exists in the file itself (ignoring defaults).
- path
- relative path
Returns true if set in the file
public Set<String> keys()
Returns the keys of this section. If the section exists in the file, only the file's keys are returned (a section a user trimmed is not refilled from defaults); otherwise the defaults' keys.
Returns keys in file order
public ConfigSection section(String path)
Returns a child section.
- path
- relative path
Returns the section
Throws ConfigException if the path holds a value that is not a section, or is missing
public Optional<ConfigSection> optionalSection(String path)
Returns a child section if present.
- path
- relative path
Returns the section, or empty
public String getString(String path)
Returns a required string.
- path
- relative path
Returns value
public String getString(String path, String fallback)
Returns a string or a fallback.
- path
- relative path
- fallback
- returned when missing
Returns value
public int getInt(String path)
Returns a required int.
- path
- relative path
Returns value
public int getInt(String path, int fallback)
Returns an int or a fallback.
- path
- relative path
- fallback
- returned when missing
Returns value
public long getLong(String path)
Returns a required long.
- path
- relative path
Returns value
public long getLong(String path, long fallback)
Returns a long or a fallback.
- path
- relative path
- fallback
- returned when missing
Returns value
public double getDouble(String path)
Returns a required double.
- path
- relative path
Returns value
public double getDouble(String path, double fallback)
Returns a double or a fallback.
- path
- relative path
- fallback
- returned when missing
Returns value
public boolean getBoolean(String path)
Returns a required boolean (true/false, also yes/no, on/off).
- path
- relative path
Returns value
public boolean getBoolean(String path, boolean fallback)
Returns a boolean or a fallback.
- path
- relative path
- fallback
- returned when missing
Returns value
public Duration getDuration(String path)
Returns a required duration written like "30s", "1h30m", or a number of seconds.
- path
- relative path
Returns value
public Duration getDuration(String path, Duration fallback)
Returns a duration or a fallback.
- path
- relative path
- fallback
- returned when missing
Returns value
public <E extends Enum<E>> E getEnum(String path, Class<E> type)
Returns a required enum constant (case-insensitive; - and spaces match _).
- path
- relative path
- type
- enum class
Returns value
public List<String> getStringList(String path)
Returns a required list of strings. A single scalar is treated as a one-element list.
- path
- relative path
Returns unmodifiable list
public <T> List<T> getList(String path, Class<T> elementType)
Returns a required list with typed elements.
- path
- relative path
- elementType
- element type
Returns unmodifiable list
public <T> T get(String path, Class<T> type)
Returns a required value converted to any supported type: scalars, enums, UUID, Duration, types with a registered TypeSerializer, and POJOs with a no-argument constructor (fields mapped from kebab-case keys; missing keys keep field defaults).
- path
- relative path
- type
- target type
Returns value
public <T> T get(String path, Class<T> type, T fallback)
Returns a value converted to a type, or a fallback when missing. Present but invalid values still throw.
- path
- relative path
- type
- target type
- fallback
- returned when missing
Returns value
public <T> T as(Class<T> type)
Maps this whole section to a POJO (see get).
- type
- POJO type
Returns mapped object
public void set(String path, Object value)
Sets a value in memory (call YamlConfig.save to write it). Values are serialised with the registered serializers; null removes the key.
- path
- relative path
- value
- value
public void remove(String path)
Removes a value in memory.
- path
- relative path
io.github.crownalonedev.bloom.config
ConfigValidation class
public final class ConfigValidation
Collects validation rules and reports every problem at once. Created by YamlConfig.validate. config.validate() .require("database.type") .oneOf("database.type", "sqlite", "mysql", "mariadb") .range("limits.homes", 1, 100) .type("cooldowns.pearl", java.time.Duration.class) .check(); // throws ConfigException listing all problems with line numbers
Since 0.1.0
8 members
public ConfigValidation require(String path)
Requires a value to exist (in the file or defaults).
- path
- path
Returns this validation
public ConfigValidation type(String path, Class<?> type)
Requires a present value to convert to a type.
- path
- path
- type
- expected type
Returns this validation
public ConfigValidation range(String path, double min, double max)
Requires a present numeric value to lie in an inclusive range.
- path
- path
- min
- minimum
- max
- maximum
Returns this validation
public ConfigValidation oneOf(String path, String... allowed)
Requires a present text value to be one of the allowed values (case-insensitive).
- path
- path
- allowed
- allowed values
Returns this validation
public ConfigValidation matches(String path, Pattern pattern, String description)
Requires a present text value to match a regular expression.
- path
- path
- pattern
- pattern the whole value must match
- description
- human description of the expected format
Returns this validation
public <T> ConfigValidation check(String path, Class<T> type, Predicate<T> rule, String message)
Adds a custom rule on a present value.
- path
- path
- type
- type to convert the value to
- rule
- condition that must hold
- message
- problem description if the rule fails, e.g. "must be a power of two"
Returns this validation
public List<String> problems()
Returns the problems found so far.
Returns problem descriptions
public void check()
Throws if any rule failed.
Throws ConfigException listing every problem
io.github.crownalonedev.bloom.config
MigrationContext class
public final class MigrationContext
Mutable access to configuration values during a ConfigMigration. Paths are dot-separated.
Since 0.1.0
6 members
public int fromVersion()
Returns the version being migrated from.
Returns source version; the migration produces fromVersion() + 1
public boolean has(String path)
Returns whether a value exists.
- path
- path
Returns true if present
public Object get(String path)
Returns a raw value (string, number, boolean, list or map).
- path
- path
Returns value, or null
public void set(String path, Object value)
Sets a raw value; null removes it.
- path
- path
- value
- value
public void remove(String path)
Removes a value.
- path
- path
public void move(String from, String to)
Moves a value (including whole sections). Does nothing if the source is missing; replaces the target.
- from
- source path
- to
- target path
io.github.crownalonedev.bloom.config
TypeSerializer interface
public interface TypeSerializer<T>
Converts a custom type to and from plain YAML values (strings, numbers, booleans, lists and maps). TypeSerializer<Location> location = new TypeSerializer<Location>() { public Location deserialize(Object raw) { String[] p = raw.toString().split(","); return new Location(Bukkit.getWorld(p[0]), Double.parseDouble(p[1]), ...); } public Object serialize(Location value) { return value.getWorld().getName() + "," + value.getX() + ...; } }; YamlConfig config = YamlConfig.builder(path).serializer(Location.class, location).build();
Since 0.1.0
2 members
public T deserialize(Object raw)
Converts a YAML value to the type.
- raw
- value as loaded from YAML (never null)
Returns converted value
Throws IllegalArgumentException with a short reason if the value cannot be converted; Bloom adds the file, key and line to the message
public Object serialize(T value)
Converts the type to a YAML value.
- value
- value (never null)
Returns a string, number, boolean, list or map
io.github.crownalonedev.bloom.config
YamlConfig class
public final class YamlConfig extends ConfigSection
A YAML configuration file with bundled defaults, typed access, validation, migrations and safe writes. YamlConfig config = YamlConfig.builder(getDataFolder().toPath().resolve("config.yml")) .defaults(() -> getResource("config.yml")) .logger(getLogger()) .build(); // creates the file from defaults if missing, then loads it String prefix = config.getString("messages.prefix"); int maxHomes = config.getInt("homes.max", 3); Settings s = config.get("settings", Settings.class); // POJO mapping Safety • A missing file is created by copying the defaults resource byte-for-byte (comments included). • Existing files are never rewritten implicitly, except by migrations (which first copy the file to a timestamped .bak) and by Builder.addMissingDefaults (opt-in, also backed up). • save and migrations edit the file's YAML node tree, so comments and formatting of untouched keys are preserved. Writes are atomic (temporary file + move). • reload keeps the previous values if the new file is invalid. • A file whose version is newer than the plugin supports is rejected rather than downgraded. Values are loaded with SnakeYAML's SafeConstructor (no arbitrary object construction), duplicate keys are rejected and alias expansion is limited. Thread-safe.
Since 0.1.0
7 members
public static YamlConfig.Builder builder(Path file)
Starts configuring a YAML file.
- file
- path of the config file
Returns builder
public Path file()
Returns the file.
Returns path
public int version()
Returns the configured target version, or 0 when versioning is not used.
Returns version
public void reload()
Re-reads the file. On failure the previous values stay active and the exception is thrown.
Throws ConfigException if the file is invalid or a migration fails
public void save()
Writes the current values to the file, preserving comments and formatting of unchanged keys. Atomic.
Throws ConfigException on I/O failure
public ConfigValidation validate()
Starts a validation of the current values.
Returns validation builder; call ConfigValidation.check to throw on problems
io.github.crownalonedev.bloom.config
YamlConfig.Builder class
public static final class Builder
Builder for YamlConfig.
8 members
public YamlConfig.Builder defaults(Supplier<InputStream> source)
Sets the bundled defaults, usually () -> plugin.getResource("config.yml"). The stream is read once per load and closed.
- source
- supplies the defaults YAML; returning null is reported as a missing resource
Returns this builder
public YamlConfig.Builder version(int currentVersion)
Enables versioned migrations with the key config-version.
- currentVersion
- version this plugin writes, >= 1
Returns this builder
public YamlConfig.Builder version(String key, int currentVersion)
Enables versioned migrations with a custom key. Files without the key are treated as version 1.
- key
- version key at the top level
- currentVersion
- version this plugin writes, >= 1
Returns this builder
public YamlConfig.Builder migration(int fromVersion, ConfigMigration migration)
Registers the migration from fromVersion to fromVersion + 1.
- fromVersion
- source version
- migration
- migration
Returns this builder
public YamlConfig.Builder addMissingDefaults(boolean enabled)
Writes settings that exist in the defaults but not in the file into the file on load (with their default comments). The file is backed up first. Off by default.
- enabled
- flag
Returns this builder
public YamlConfig.Builder logger(Logger target)
Sets a logger for informational messages (file created, migrated).
- target
- logger, usually plugin.getLogger()
Returns this builder
public <T> YamlConfig.Builder serializer(Class<T> type, TypeSerializer<T> serializer)
Registers a serializer for a custom type.
- type
- type
- serializer
- serializer
Returns this builder
public YamlConfig build()
Creates the config and loads it (creating the file from defaults if needed and running migrations).
Returns the loaded config
Throws ConfigException if loading fails
bloom-storage
Bloom Storage: asynchronous JDBC (SQLite, MySQL, MariaDB) with pooling, transactions, migrations and repositories.
io.github.crownalonedev.bloom.storage
BlockingDatabase class
public final class BlockingDatabase implements SqlOperations
Synchronous database access for code that already runs off the main thread (for example inside scheduler().async(...) or a CompletableFuture chain). Obtain with Database.blocking. Every method throws IllegalStateException when called on the main server thread (as reported by the mainThreadCheck given to the database builder), because blocking JDBC calls there freeze the server.
Since 0.1.0
5 members
public int update(String sql, Object... params)
- sql
- String
- params
- Object[]
public Optional<Long> insert(String sql, Object... params)
- sql
- String
- params
- Object[]
public int[] batch(String sql, List<Object[]> rows)
- sql
- String
- rows
- List<Object[]>
public <T> List<T> query(String sql, RowMapper<T> mapper, Object... params)
- sql
- String
- mapper
- RowMapper<T>
- params
- Object[]
public <T> Optional<T> queryOne(String sql, RowMapper<T> mapper, Object... params)
- sql
- String
- mapper
- RowMapper<T>
- params
- Object[]
io.github.crownalonedev.bloom.storage
Database class
public final class Database implements Terminable
A pooled SQL database with an asynchronous API. Database db = Database.builder() .sqlite(getDataFolder().toPath().resolve("data.db")) .mainThreadCheck(bloom.scheduler()::isPrimaryThread) .logger(getLogger()) .build(); db.migrate(migrations).join(); // acceptable in onEnable: the server is not ticking yet db.queryOne("SELECT kills FROM stats WHERE uuid = ?", rs -> rs.getInt(1), player.getUniqueId()) .thenAcceptAsync(kills -> player.sendMessage("Kills: " + kills.orElse(0)), bloom.scheduler().mainThreadExecutor()); // back on the main thread Threading Operations run on a bounded pool of database threads (one per connection). Returned futures complete on those threads: switch to the main thread with thenAcceptAsync(..., mainThreadExecutor()) before touching game state. When the queue is full (default 1000 pending operations) new operations fail immediately with StorageException instead of piling up unbounded work. Shutdown close stops accepting work, waits for queued operations (default up to 10 s), fails any operation that could not run, and closes the pool. Call it in onDisable; when a Bloom instance owns it (registered in the service registry) Bloom closes it automatically.
Since 0.1.0
15 members
public static Database.Builder builder()
Starts configuring a database.
Returns builder
public Dialect dialect()
Returns the dialect.
Returns dialect
public BlockingDatabase blocking()
Returns synchronous access for code already running off the main thread.
Returns blocking API
public int pendingOperations()
Returns the number of queued operations that have not started yet.
Returns queue size
public CompletableFuture<Integer> update(String sql, Object... params)
Executes an INSERT/UPDATE/DELETE/DDL statement asynchronously.
- sql
- statement
- params
- parameters (see SqlOperations for supported types)
Returns future with the affected row count
public CompletableFuture<Optional<Long>> insert(String sql, Object... params)
Executes an INSERT asynchronously and returns the generated key.
- sql
- statement
- params
- parameters
Returns future with the generated key, if any
public CompletableFuture<int[]> batch(String sql, List<Object[]> rows)
Executes a JDBC batch asynchronously.
- sql
- statement
- rows
- parameter rows
Returns future with per-row update counts
public <T> CompletableFuture<List<T>> query(String sql, RowMapper<T> mapper, Object... params)
Runs a query asynchronously.
- sql
- query
- mapper
- row mapper (runs on a database thread)
- params
- parameters
Returns future with all mapped rows
public <T> CompletableFuture<Optional<T>> queryOne(String sql, RowMapper<T> mapper, Object... params)
Runs a single-row query asynchronously.
- sql
- query
- mapper
- row mapper (runs on a database thread)
- params
- parameters
Returns future with the first row, or empty
public <T> CompletableFuture<T> transaction(Function<Transaction,T> work)
Runs work in a transaction and returns its result. Commits when work returns, rolls back if it throws.
- work
- transaction body (runs on a database thread)
Returns future with the result
public CompletableFuture<Void> inTransaction(Consumer<Transaction> work)
Runs work without a result in a transaction.
- work
- transaction body (runs on a database thread)
Returns future completed when committed
public <T> CompletableFuture<T> withConnection(Database.ConnectionWork<T> work)
Gives raw JDBC access on a database thread. The connection is returned to the pool afterwards.
- work
- connection callback
Returns future with the result
public CompletableFuture<MigrationResult> migrate(List<Migration> migrations)
Applies pending migrations in version order, recording them in the history table (default bloom_schema_history; configurable with Builder.migrationTable).
- migrations
- all migrations of the plugin
Returns future with the result; fails if a migration fails or the database is newer than the migrations
public void close()
Stops accepting operations, waits for queued work, fails work that could not run and closes the pool. Idempotent. Blocks for at most the configured shutdown timeout.
public boolean isClosed()
io.github.crownalonedev.bloom.storage
Database.Builder class
public static final class Builder
Builder for Database.
16 members
public Database.Builder sqlite(Path file)
Uses an SQLite file. Parent directories are created. The pool has one connection by default, which serialises writes and avoids SQLITE_BUSY.
- file
- database file
Returns this builder
public Database.Builder mysql(String host, int port, String database, String user, String pass)
Uses MySQL.
- host
- host name
- port
- port, usually 3306
- database
- schema name
- user
- user name
- pass
- password
Returns this builder
public Database.Builder mariadb(String host, int port, String database, String user, String pass)
Uses MariaDB (shade org.mariadb.jdbc:mariadb-java-client into your plugin).
- host
- host name
- port
- port, usually 3306
- database
- schema name
- user
- user name
- pass
- password
Returns this builder
public Database.Builder jdbcUrl(String url, String user, String pass, Dialect type)
Uses a custom JDBC URL.
- url
- JDBC URL
- user
- user name, may be null
- pass
- password, may be null
- type
- dialect of the database
Returns this builder
public Database.Builder poolSize(int size)
Sets the number of connections and database threads (default 1 for SQLite, 8 otherwise).
- size
- pool size, >= 1
Returns this builder
public Database.Builder queueCapacity(int capacity)
Sets the maximum number of queued operations before new ones fail fast (default 1000).
- capacity
- queue capacity
Returns this builder
public Database.Builder connectionTimeout(Duration timeout)
Sets how long to wait for a free connection (default 10 s).
- timeout
- timeout
Returns this builder
public Database.Builder maxLifetime(Duration lifetime)
Sets the maximum lifetime of pooled connections (default 30 min; keep it below the server's wait_timeout).
- lifetime
- lifetime
Returns this builder
public Database.Builder shutdownTimeout(Duration timeout)
Sets how long Database.close waits for queued work (default 10 s).
- timeout
- timeout
Returns this builder
public Database.Builder poolName(String name)
Sets the pool and thread name prefix (default "Bloom"); use your plugin name.
- name
- pool name
Returns this builder
public Database.Builder migrationTable(String table)
Sets the migration history table (default bloom_schema_history). Plugins sharing one MySQL schema must use different tables, e.g. "myplugin_schema_history".
- table
- table name
Returns this builder
public Database.Builder driverClassName(String className)
Forces a JDBC driver class instead of auto-detection.
- className
- driver class
Returns this builder
public Database.Builder property(String key, String value)
Adds a driver/data-source property (e.g. useSSL=true).
- key
- property
- value
- value
Returns this builder
public Database.Builder mainThreadCheck(BooleanSupplier check)
Tells the database how to detect the main server thread, so BlockingDatabase can refuse to block it. With Bloom: bloom.scheduler()::isPrimaryThread.
- check
- returns true on the main thread
Returns this builder
public Database.Builder logger(Logger target)
Sets the logger for migrations and shutdown messages.
- target
- logger, usually plugin.getLogger()
Returns this builder
public Database build()
Opens the pool. Fails fast if the database is unreachable.
Returns the database
Throws StorageException with a diagnostic message if the pool cannot start
io.github.crownalonedev.bloom.storage
Database.ConnectionWork interface
public static interface ConnectionWork<T>
Raw JDBC callback for withConnection.
1 member
public T apply(Connection connection) throws SQLException
Uses the connection.
- connection
- pooled connection; do not close it
Returns result
Throws SQLException on JDBC errors
io.github.crownalonedev.bloom.storage
Dialect enum
public final enum Dialect
SQL dialects Bloom knows about. Used for driver defaults and small SQL helpers; Bloom does not rewrite your SQL.
Since 0.1.0
7 members
public static Dialect[] values()
public static Dialect valueOf(String name)
- name
- String
SQLITE
SQLite (file database).
MYSQL
MySQL. Bloom tries Connector/J 8+ first, then the 5.x driver bundled with legacy servers.
MARIADB
MariaDB (Connector/J must be shaded into your plugin).
public List<String> driverClasses()
Returns candidate JDBC driver classes, in preference order.
Returns driver class names
public String upsert(String table, List<String> columns, List<String> keyColumns)
Builds an insert-or-update statement with ? placeholders for every column, in order. • SQLite: INSERT OR REPLACE (works on the old SQLite bundled with 1.8 servers; note that it deletes and re-inserts the row, so ON DELETE CASCADE children are removed) • MySQL/MariaDB: INSERT ... ON DUPLICATE KEY UPDATE
- table
- table name
- columns
- all columns, primary key columns included
- keyColumns
- primary/unique key columns (not updated on conflict)
Returns SQL
io.github.crownalonedev.bloom.storage
Migration class
public final class Migration
A numbered schema change, applied once per database by Database.migrate. List<Migration> migrations = Arrays.asList( Migration.of(1, "create stats", "CREATE TABLE IF NOT EXISTS stats (uuid VARCHAR(36) PRIMARY KEY, kills INT NOT NULL DEFAULT 0)"), Migration.of(2, "add deaths", tx -> tx.update("ALTER TABLE stats ADD COLUMN deaths INT NOT NULL DEFAULT 0"))); database.migrate(migrations).join(); // blocking is acceptable in onEnable, before players join Each migration runs in its own transaction. Note that MySQL/MariaDB commit DDL statements immediately, so a failing multi-statement migration can leave earlier statements applied there; keep migrations small.
Since 0.1.0
4 members
public static Migration of(int version, String description, String... statements)
Creates a migration from SQL statements.
- version
- unique positive version
- description
- short description stored in the history table
- statements
- statements to execute in order
Returns migration
public static Migration of(int version, String description, Migration.Step step)
Creates a migration with custom logic (e.g. dialect-specific SQL or data transformation).
- version
- unique positive version
- description
- short description
- step
- migration body
Returns migration
public int version()
Returns the version.
Returns version
public String description()
Returns the description.
Returns description
io.github.crownalonedev.bloom.storage
Migration.Step interface
public static interface Step
Migration body.
1 member
public void apply(Transaction transaction)
Applies the change.
- transaction
- transaction to execute statements in
io.github.crownalonedev.bloom.storage
MigrationResult class
public final class MigrationResult
Outcome of Database.migrate.
Since 0.1.0
4 members
public int previousVersion()
Returns the schema version before migrating.
Returns version, 0 for a new database
public int currentVersion()
Returns the schema version after migrating.
Returns version
public List<Integer> applied()
Returns the versions applied by this run.
Returns applied versions in order
io.github.crownalonedev.bloom.storage
Repository interface
public interface Repository<K, V>
A minimal asynchronous repository. Bloom provides SqlRepository as a simple SQL implementation; implement this interface yourself for other stores (files, Redis, ...) so callers do not depend on the storage technology.
Since 0.1.0
4 members
public CompletableFuture<Optional<V>> find(K key)
Loads a value.
- key
- key
Returns future with the value, or empty
public CompletableFuture<List<V>> findAll()
Loads all values. Avoid on large tables.
Returns future with all values
public CompletableFuture<Void> save(V value)
Inserts or updates a value.
- value
- value
Returns future completed when saved
public CompletableFuture<Boolean> delete(K key)
Deletes a value.
- key
- key
Returns future with true if a value was deleted
io.github.crownalonedev.bloom.storage
RowMapper interface
public interface RowMapper<T>
Maps the current row of a ResultSet to an object. Do not call next() inside the mapper. RowMapper<PlayerStats> mapper = rs -> new PlayerStats( UUID.fromString(rs.getString("uuid")), rs.getInt("kills"), rs.getInt("deaths"));
Since 0.1.0
1 member
public T map(ResultSet row) throws SQLException
Maps the current row.
- row
- result set positioned on a row
Returns mapped object
Throws SQLException on column access errors
io.github.crownalonedev.bloom.storage
SqlOperations interface
public interface SqlOperations
Synchronous SQL operations. Implemented by Transaction (one connection, inside Database.transaction) and BlockingDatabase (for code already running off the main thread). Parameters ? placeholders are bound in order. Supported parameter types: null, String, numbers, Boolean, byte[], UUID (stored as its 36-character string), enums (stored by name()), java.time.Instant (stored as epoch milliseconds, a BIGINT), Duration (milliseconds) and any type the JDBC driver accepts in setObject.
Since 0.1.0
5 members
public int update(String sql, Object... params)
Executes an INSERT, UPDATE, DELETE or DDL statement.
- sql
- statement with ? placeholders
- params
- parameter values
Returns affected row count
Throws StorageException on failure
public Optional<Long> insert(String sql, Object... params)
Executes an INSERT and returns the generated key.
- sql
- insert statement
- params
- parameter values
Returns generated key, or empty if the statement generated none
Throws StorageException on failure
public int[] batch(String sql, List<Object[]> rows)
Executes a statement once per parameter row, as a JDBC batch.
- sql
- statement with ? placeholders
- rows
- parameter rows
Returns affected row counts per row (drivers may report -2, "success, count unknown")
Throws StorageException on failure
public <T> List<T> query(String sql, RowMapper<T> mapper, Object... params)
Runs a query and maps every row.
- sql
- query
- mapper
- row mapper
- params
- parameter values
Returns mapped rows, possibly empty
Throws StorageException on failure
public <T> Optional<T> queryOne(String sql, RowMapper<T> mapper, Object... params)
Runs a query expected to return at most one row.
- sql
- query
- mapper
- row mapper
- params
- parameter values
Returns the first row, or empty
Throws StorageException on failure
io.github.crownalonedev.bloom.storage
SqlRepository abstract class
public abstract class SqlRepository<K, V> implements Repository<K,V>
A Repository for one table with a single-column primary key. Subclasses describe the mapping; Bloom generates the SQL. Table and column names must be plain identifiers (they are validated to prevent accidental SQL injection through names). final class StatsRepository extends SqlRepository<UUID, PlayerStats> { StatsRepository(Database db) { super(db, "player_stats", "uuid", Arrays.asList("uuid", "kills", "deaths"), rs -> new PlayerStats(UUID.fromString(rs.getString("uuid")), rs.getInt("kills"), rs.getInt("deaths"))); } protected UUID keyOf(PlayerStats s) { return s.uuid(); } protected Object[] valuesOf(PlayerStats s) { return new Object[] {s.uuid(), s.kills(), s.deaths()}; } }
Since 0.1.0
9 members
protected SqlRepository(Database database, String table, String keyColumn, List<String> columns, RowMapper<V> mapper)
Creates the repository.
- database
- database
- table
- table name
- keyColumn
- primary key column
- columns
- all columns including the key, in the order of valuesOf
- mapper
- maps a row to a value
protected abstract K keyOf(V value)
Returns the key of a value.
- value
- value
Returns key
protected abstract Object[] valuesOf(V value)
Returns the column values of a value, in the order of the constructor's columns.
- value
- value
Returns column values
protected Database database()
Returns the database.
Returns database
protected String table()
Returns the table name.
Returns table
public CompletableFuture<Optional<V>> find(K key)
- key
- K
public CompletableFuture<List<V>> findAll()
public CompletableFuture<Void> save(V value)
- value
- V
public CompletableFuture<Boolean> delete(K key)
- key
- K
io.github.crownalonedev.bloom.storage
StorageException class
public class StorageException extends BloomException
Thrown (or used to complete futures exceptionally) when a database operation fails. The message includes the SQL statement (without parameter values) when relevant.
Since 0.1.0
2 members
public StorageException(String message)
Creates an exception.
- message
- description
public StorageException(String message, Throwable cause)
Creates an exception with a cause.
- message
- description
- cause
- cause, usually a SQLException
io.github.crownalonedev.bloom.storage
Transaction interface
public interface Transaction extends SqlOperations
Operations inside a database transaction. All statements share one connection; the transaction commits when the callback returns and rolls back if it throws. Only valid inside Database.transaction.
Since 0.1.0
2 members
public Dialect dialect()
Returns the database dialect.
Returns dialect
public Connection connection()
Returns the underlying connection for advanced JDBC use. Do not close it or change auto-commit.
Returns connection