Links
Tags
Creators
Details
2.4.0
Compatibility
Changes
Ultimate Broadcast 2.4.0 โ the rescue release
This update fixes the two reasons 2.1.0โ2.3.0 lost most of their downloads: a broken default config that could stop the plugin from starting, and missing Minecraft version tags that hid the newest builds from 1.21.5+ servers. It also adds the features players and server owners actually asked for.
๐ฅ Critical fixes
The plugin could fail to start on a fresh install
config.yml shipped in 2.1.0โ2.3.0 had gui.title indented with three spaces while its siblings used two. Bukkit refuses to parse that file, so the plugin could disable itself on first start โ which is why 2.1.0 only ever reached a handful of downloads while 2.0.2 kept being downloaded.
2.4.0:
- ships a valid configuration,
- detects the exact broken layout on existing installs,
- writes a timestamped backup (
config.backup-<date>.yml), - repairs the indentation in place,
- and starts normally.
Your comments and custom values are preserved โ the file is fixed, not replaced.
The newest builds were invisible on modern Minecraft
2.3.0 was published with game_versions ending at 1.21.4, even though 2.0.2 supported up to 1.21.11. Servers on 1.21.5โ26.3 could not install the newer version at all.
2.4.0 is listed for every version from 1.21 through 26.3, verified on Paper 1.21.4, Paper 26.3 and Folia 26.3.
๐ Other bugs fixed
| Bug | Impact | Fix |
|---|---|---|
Sound.valueOf(...) used at runtime |
On 1.21.4+ Sound became an interface, so the call throws NoSuchMethodError and sounds break |
Registry-based resolver with enum fallback and a per-name cache |
MySQL schema used AUTOINCREMENT and SQLite-only ON CONFLICT |
"MySQL support" could never create its tables | Dialect-aware DDL, portable upserts, epoch-millis timestamps |
| SQLite driver class pointed at a relocated package | Database could silently stay uninitialised | Storage rewritten without shading/relocation, verified on startup |
| GUI listener cancelled every inventory click on the server | Players could not use any other plugin's GUI | Clicks are only handled when our own InventoryHolder is open |
GUI item names were Component.toString() dumps |
Menus displayed TextComponentImpl{...} garbage |
Real Adventure components for titles, names and lore |
| Scheduled entries were loaded from config and database | Every reload duplicated announcements | Config is the single source of truth |
random-messages.interval-minutes and per-message weight ignored |
Random pool fired on the scheduler interval and picked uniformly | Dedicated weighted rotation on its own interval |
| PlaceholderAPI only applied when a sender existed | %player%/PAPI placeholders were never resolved in scheduled messages |
Rendered per recipient, for every source |
| Countdown/actionbar required a player sender | Console could not start a countdown | Works from console |
| Titles used legacy strings | Hex gradients turned into ยงx gibberish |
Adventure Title with full RGB |
| Network relay re-broadcast its own messages | Duplicate announcements across servers | Message IDs with a dedupe window |
| SQL ran on the server thread | TPS spikes when history/preferences were written | Single background writer thread |
โจ New features
๐ Player subscription centre
/broadcast toggleโ master opt-out./broadcast toggle eventsโ per-category opt-out./broadcast settingsโ GUI with a toggle per category.- Configurable categories with display names, descriptions, default state and permission.
- Preferences stored in SQLite/MySQL and loaded asynchronously on join.
- Filtering happens before rendering, so opted-out players cost nothing.
๐ฌ Discord mirroring (no bot required)
- Webhook-based, runs on its own daemon thread.
- Rate-limit aware, retries transient failures, respects
429. - Choose which events mirror:
manual,scheduled,random,countdown. - Configurable username, avatar, colour, footer and optional
@everyonefor manual broadcasts. /broadcast discord testverifies the setup.
๐ Five delivery channels
/broadcast send <chat|actionbar|title|subtitle|bossbar> <message> โ plus the legacy /broadcast title, /broadcast actionbar shortcuts.
๐งต True Folia support
- Runtime Folia detection.
- Global region scheduler for timers, async scheduler for storage, per-entity scheduler for player messages.
- Verified on Folia 26.3: timers fire on the region scheduler and messages are dispatched per player.
๐ง Delivery guard
- Duplicate window (proxy echo protection).
- Hard per-second cap.
- TPS-aware effects (chat still sends, sounds/particles pause).
- Minimum-player rule.
- Per-player cooldowns for scheduled entries.
โ๏ธ Operations
/broadcast statsโ totals, players reached, duplicate drops, storage backend, Discord health, live TPS./broadcast historyโ last 20 announcements from the database./broadcast listโ next run time for every scheduled entry.settings.debug: truelogs exactly why an announcement was skipped.- Safe
/broadcast reloadthat restarts schedulers without duplicating tasks.
๐ PlaceholderAPI
New placeholders, all served from memory:
%ultimatebroadcast_total%, %ultimatebroadcast_scheduled%, %ultimatebroadcast_delivered%, %ultimatebroadcast_duplicates%, %ultimatebroadcast_enabled%, %ultimatebroadcast_cooldown%, %ultimatebroadcast_subscribed_<category>%.
โก Performance & reliability
- No SQL on the server thread. History, stats and preferences are queued to a single daemon writer; SQLite runs in WAL mode with a single writer, eliminating
database is lockedunder load. - Messages without placeholders are parsed once per broadcast, not once per player.
- One 1-second ticker replaces one Bukkit task per scheduled entry; intervals no longer drift and
/reloadcannot pile up duplicate tasks. - Sound and particle lookups are cached after the first resolve.
- Effects back off automatically below your TPS threshold.
- History is pruned automatically to
settings.history-limit.
๐งฉ Compatibility
| Minecraft | 1.21, 1.21.1โ1.21.11, 26.1, 26.1.1, 26.1.2, 26.2, 26.3 |
| Platforms | Paper, Purpur, Folia |
| Java | 21+ (26.x servers require Java 25, as always) |
| Optional | PlaceholderAPI |
Verified during this release: Paper 1.21.4 (Java 21), Paper 26.3 (Java 25), Folia 26.3 (Java 25) โ plugin enabled, all five channels delivered, scheduler fired, database writes confirmed.
Spigot/Bukkit are no longer listed. The plugin uses Adventure components for hex colours and titles, which Spigot does not provide; the 2.x Spigot listing could not actually enable. Listing only Paper/Purpur/Folia keeps the download button honest.
โฌ๏ธ Upgrading from 2.x
- Drop the new jar in
plugins/and restart. - Your config is migrated automatically:
- invalid YAML is repaired (with a backup),
settings.database/countdown.databasemove to the new top-leveldatabasesection in memory,settings.bungeecord-supportandsettings.cross-server-channelmap to the newnetworksection.
- The old
minecraft.dbSQLite file is renamed tobroadcast.dbโ data is preserved. - Permission change:
ultimatebroadcast.usenow defaults to op (2.x defaulted to true, letting any player broadcast). Grant it explicitly to staff or VIP ranks if needed. /broadcast enable|disableis now a runtime switch and no longer rewritesconfig.yml.
No config keys were removed. Old gui.items, scheduler.broadcasts, template, countdown and default-* sections keep working.
๐ฆ Technical details
- Build: Java 21 target, Paper API 1.21, shaded SQLite + MySQL drivers, no external plugin dependencies.
- Storage tables:
broadcast_history,broadcast_stats,broadcast_preferences. - All three tables are created automatically on both SQLite and MySQL.
If 2.1โ2.3 broke your server: sorry. 2.4.0 is the version that should have shipped. Please open an issue with your log if anything still misbehaves.
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:yo3x10ea:KAWPAUyn"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:yo3x10ea:KAWPAUyn"
}

