Tags
Creators
Details
4.0.0
Compatibility
Changes
4.0.0 – 2026-04-18
This is a complete rewrite of the plugin. Player state lives in a database instead of a YAML file, commands have been regrouped into nested subcommands, and a long list of new features landed. Legacy config.yml works unchanged and every pre-4.0 command name is still routable as an alias, so upgrades are drop-in for server admins. Plugins consuming the Java API need to update their imports – see Breaking below.
⚠️ Breaking
- Java package renamed from
cz.boosik.boosCooldown→software.boos.boosCooldown. Plugins that depend onBoosCooldownAPIor the custom events must update their imports and addloadbefore: [boosCooldowns]to theirplugin.yml. - Minimum Java version raised from 8 to 21.
- Maven groupId changed from
cz.boosiktosoftware.boos.
✨ Added
Persistence
- Database-backed state – SQLite (default, zero-config) or MySQL / MariaDB for networks.
- Schema-versioned migrations (V1 initial, V2 user_preferences, V3 audit_log, V4 config_version).
- HikariCP connection pool with leak detection.
- Auto-migration of legacy
users.ymlon first start (old file renamed tousers.yml.migrated-<timestamp>). - JDBC drivers auto-downloaded via
libraries:inplugin.yml.
Multi-server
- Cooldowns, limits, server cooldowns, user preferences and scheduled resets shared across every server pointing at the same MySQL/MariaDB.
- Server-wide cooldowns (
server_cooldown:) – one player using a command blocks everyone else on the network for the window. - Config drift detection – each node hashes
config.ymlon enable and on/bcd reload, a periodic monitor logs a warning when peers disagree,/bcd diffreports which nodes differ. options.options.node_idfor human-readable node labels.
Per-command rules
- Progressive cooldowns via
cooldown_multiplierandcooldown_reset_after. - Per-world restrictions (
worlds: [survival, nether]). - WorldGuard regions (
regions: [spawn, arena]) as soft-depend. - Group inheritance via
_inherits: defaultso VIP groups only override what changes. - Disable commands via
disabled: truewithout unregistering them. - Per-command messages (
cooldown_message,warmup_message,disabled_message,server_cooldown_message) with per-player PlaceholderAPI expansion.
Player UX
- Boss bar progress indicator during warmup.
- Action bar for warmup countdown and cooldown notices on attempt.
- Warmup sounds (
warmup_sound,complete_sound) and particles (warmup_particle) per command. - Confirmation dialogs – clickable
[Yes]/[No]for commands with a price/limit, per-player toggle persisted in DB. - Refund on warmup cancel (
refund_on_warmup_cancel) – returns money, items and XP when a warmup is aborted. - Localization – drop a
messages_<locale>.ymland messages follow the client language. Bundled example:messages_cs.yml.
Admin tooling
- Commands regrouped under
/bcd clear,/bcd rule,/bcd grant,/bcd resetgroups. - New subcommands:
status,check,clear all,rule get,grant uses,tempset,validate,audit,diff,help. - Autogenerated
/bcd help– permission-filtered, grouped into Player / Administration / Diagnostics sections. - Smart tab completion – suggests option keys, online players, configured commands at every level.
/bcd validate– config linter catches unknown option keys, invalid durations, typos in materials and sounds./bcd tempset– option override that auto-restores after a duration.- Legacy aliases – every pre-4.0 command name (
clearcooldowns,set,info,scheduleglobalreset, …) still routes to its new home.
Automation
- Event-based cooldown resets via
event_triggers:– clear a player's cooldown when they kill a specific entity or earn an advancement, with optional chat message, sound cue and server-wide broadcast. - Scheduled global limit resets via
/bcd reset schedule <cmd> <time>, visible through/bcd reset list, persisted in DB. - Namespace-aware command handling (
apply_rules_to_prefixed_syntax: true) – rewrites/minecraft:tp→/tpso plugin rules still apply, without needing the hard syntax blocker.
Integrations
- PlaceholderAPI expansion registered automatically:
%boos_remaining_<cmd>%,%boos_remaining_seconds_<cmd>%,%boos_on_cooldown_<cmd>%,%boos_server_cooldown_<cmd>%,%boos_uses_<cmd>%,%boos_uses_remaining_<cmd>%. - Foreign placeholders inside plugin messages – any
%vault_eco_balance%/%luckperms_primary_group%etc. resolves per-player in cooldown/warmup/disabled messages. - Vault, PlayerPoints, WorldGuard, LuckPerms detected at runtime; missing integration disables its feature, never breaks startup.
- bStats – 13 custom charts covering storage backend (with driver version drill-down), feature toggles, detected integrations, multi-node setup, locale distribution, config scale, warmup cancel sources.
Developer
- Public
BoosCooldownAPIfacade withisOnCooldown,setCooldown,getRemainingUses, etc. - Custom cancellable Bukkit events:
CooldownEvent,WarmupEvent,CommandEvent. - 142 tests – JUnit 5 + Mockito + MockBukkit integration tests; full CI workflow on every PR.
- JMH benchmark for the cooldown hot-path.
- GitHub Actions CI workflow (
.github/workflows/ci.yml).
Security
- All SQL uses parameterized
PreparedStatement. - Vault / PlayerPoints / PlaceholderAPI / WorldGuard class references isolated behind
isPluginEnabledchecks andLinkageErrorcatches – plugin boots cleanly even when every optional dependency is missing. - Command pipeline wrapped in try/catch so a bug in a single check can never block every command on the server.
🔧 Changed
- Vault / PlayerPoints no longer cause
NoClassDefFoundErroron servers that don't have them – integrations are now fully soft-depend-safe. - Package structure – monolithic
BoosCoolDownListener(434 lines) split into a service / listener / command / persistence layout. StaticManagersreplaced with an injectedServicescontainer. - Build target – Paper 1.21.8 API,
plugin.ymldeclaresapi-version: "1.20"so the jar runs on Paper 1.20+ through 26.1.2 without a rebuild. - Cooldown storage key – previously
String.hashCode()(collidable, opaque), now a normalized, stableCommandKeythat's human-readable during debugging. - Timestamps –
SimpleDateFormat("dd.MM.yyyy HH:mm:ss")replaced byjava.time.Instant+ epoch-millis columns. - Hot-path reads –
PlayerCommandPreprocessEventhandler only ever touches an in-memory cache; cache is pre-warmed onPlayerJoinEventso no cache miss can hit the DB synchronously. - Command pipeline ordering – every check now runs before mutations, preventing partial charges when a later gate rejects the command (see Fixed below).
- Bundled dependencies – HikariCP and bStats are shaded and relocated under
software.boos.boosCooldown.shaded.*.
🐛 Fixed
limit_reset_delayno longer sticks at zero – previously, once a player had consumed all their uses and the reset window elapsed, theresetAttimestamp was ignored and the limit stayed at 0 forever. The service now refreshes expired windows on read.- Pipeline no longer partially charges blocked commands – when a command is blocked by insufficient funds or warmup already started, the usage counter and economy balance are no longer mutated before the rejection. Check-then-commit pattern with refund fallback.
/plugin:commandsyntax now triggers plugin rules instead of bypassing them, with the option to either reject (syntax_blocker_enabled: true) or transparently rewrite (apply_rules_to_prefixed_syntax: true).- Plugin disable no longer leaks resources –
HikariDataSource.close()is called, the async executor'sawaitTermination(5s)waits for pending DB writes,Bukkit.getScheduler().cancelTasks(this)cancels timers. Prevents SQLite file locks on Windows after/reload. - Action bar / boss bar effects properly cancelled when warmup is aborted.
Sign.getLine(int)replaced with modernSign.getSide(Side.FRONT).getLine(int)for 1.20+ sign compatibility.Bukkit.getOfflinePlayer(String)blocking I/O removed from subcommands –Bukkit.getPlayerExact(String)is used instead.- Command listener fails open – an exception inside the pipeline logs to console but leaves the event alone, so Bukkit still dispatches the command. A bug can't block every command server-wide anymore.
- Config
get("commands.groups.default./kit.limit")path handling – rewritten to traverse nestedConfigurationSections instead of string path lookup, fixing rules for commands with slashes in their key. Sound.valueOf(String)deprecation – wrapped inLinkageErrorcatch so future Paper builds that remove it will log a warning instead of crashing the effect.- HikariCP leak detection set to 10s to surface unclosed connections early.
🗑️ Removed
- Legacy
Managers/package (replaced byservice/with dependency injection). - Legacy
Listeners/package (split into purpose-specific files underlistener/). - Legacy
Runnables/duplicate. users.yml– auto-migrated into the database on first run; old file is renamed, not deleted, for safety.
📦 Upgrade notes
Drop the new jar in and start the server. On first run the plugin will:
- Create
plugins/boosCooldowns/cooldowns.db(SQLite) with V1–V4 schema applied. - Detect
users.ymlif present, migrate its contents into the DB, and rename the file tousers.yml.migrated-<epoch>. - Keep every rule from the existing
config.yml(the format is backward compatible – new keys default to backward-compatible values).
If you manage more than one server, point every instance at the same MySQL/MariaDB via the new database: section and set node_id per server.
Earlier versions of boosCooldowns are tracked in the git history.
Optional dependencies
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle. To learn more about the Modrinth Maven API, click here.
Note: When available, you should use the creator's maven repo instead as it will have transitive dependency information that the Modrinth Maven API does not. You may also end up with duplicate dependencies if you use a mix of Modrinth and non-Modrinth Maven repositories for your dependencies, because the group identifier will be different when served through the Modrinth Maven API.
Maven coordinates:
Version ID:
build.gradle:
repositories {
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
// forRepositories(fg.repository) // Uncomment when using ForgeGradle
filter {
includeGroup "maven.modrinth"
}
}
}
// Standard Gradle dependency
dependencies {
implementation "maven.modrinth:12UU7tvc:WB4ItyHY"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:12UU7tvc:WB4ItyHY"
}

