Developer API
Bosses ships with a public API and a set of Bukkit events, so other plugins can read boss state, react to fights, and even register their own ability actions — no direct dependency on Bosses' internals needed, just the API module.
0. Adding the dependency
The API is published to our own Maven repository — add it as a repository, then depend on it as compileOnly (Bosses provides the implementation at runtime, so you don't want to shade it into your own jar).
Gradle (Groovy):
Code:
repositories {
maven {
url = uri("https://repository.atlantisservices.net/repository/api/")
}
}
dependencies {
compileOnly "net.atlantisservices.bosses:api:VERSION"
}
Gradle (Kotlin DSL):
Code:
repositories {
maven("https://repository.atlantisservices.net/repository/api/")
}
dependencies {
compileOnly("net.atlantisservices.bosses:api:VERSION")
}
Maven:
Code:
<repositories>
<repository>
<id>atlantisservices-api</id>
<url>https://repository.atlantisservices.net/repository/api/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>net.atlantisservices.bosses</groupId>
<artifactId>api</artifactId>
<version>VERSION</version>
<scope>provided</scope>
</dependency>
</dependencies>
Replace VERSION with the latest release — check the repository or this resource's changelog for the current version. Since it's compileOnly/provided, you'll also need Bosses installed as a plugin on any server running your jar, same as any soft-dependency.
1. Getting the API
BossesAPI is registered on Bukkit's standard ServicesManager during startup. Grab it with:
Code:
val api = BossesAPI.get() ?: return
Which is just shorthand for:
Code:
val api = Bukkit.getServicesManager().load(BossesAPI::class.java) ?: return
Always null-check it — it'll be null if Bosses isn't installed or hasn't finished enabling yet.
2. Querying bosses
Code:
// Config lookups
val config = api.getBossConfig("block_warden")
val allConfigs = api.listBossConfigs()
// Active boss lookups
val isFighting = api.isActive("block_warden")
val byId = api.getActiveBoss("block_warden")
val byEntity = api.getActiveBoss(someEntity.uniqueId)
val allActive = api.getActiveBosses()
// Reading state off a Boss
allActive.forEach { boss ->
println("${boss.config.displayName}: ${boss.percentHp()}% hp")
println("Top damager: ${boss.topDamagers(1)}")
}
You can also spawn, force-kill, damage, or heal a boss directly through the API:
Code:
val boss = api.spawn("block_warden")
api.damageBoss(boss, attackerUuid, 50.0)
api.healBoss(boss, 100.0)
api.kill(boss) // force removal, no death rewards
3. Listening to events
All standard Bukkit events — register a normal Listener like you would for any other plugin.
Code:
class MyBossListener : Listener {
@EventHandler
fun onSpawn(event: BossSpawnEvent) {
Bukkit.broadcastMessage("${event.boss.config.displayName} has appeared!")
}
@EventHandler
fun onDeath(event: BossDeathEvent) {
Bukkit.broadcastMessage("${event.boss.config.displayName} has fallen!")
}
@EventHandler
fun onDamage(event: BossDamageEvent) {
// Cancellable, and event.damage can be modified before it's applied
if (event.attacker.hasPermission("bosses.nodamage")) {
event.isCancelled = true
}
}
@EventHandler
fun onAbilityTrigger(event: BossAbilityTriggerEvent) {
println("${event.boss.config.displayName} used ${event.ability.id}")
}
}
Register it as usual:
Code:
Bukkit.getPluginManager().registerEvents(MyBossListener(), myPlugin)
- BossSpawnEvent — fired right after a boss finishes spawning
- BossDeathEvent — fired on natural death (HP reaches 0), before rewards are handed out
- BossDamageEvent — fired before damage is applied; cancellable, and the damage amount can be modified
- BossAbilityTriggerEvent — fired every time one of a boss's abilities actually triggers
4. Registering custom ability actions
Add your own action types so server owners can reference them straight from config.yml alongside the built-in ones (sound, particle, damage_radius, summon, broadcast, heal_self, charge, command).
Code:
BossActionRegistry.register("teleport_random") { section ->
val radius = section.getDouble("radius", 10.0)
BossAction { context ->
val entity = context.activeBoss.entity
val center = entity.location
val world = center.world ?: return@BossAction
val angle = Math.random() * Math.PI * 2
val x = center.x + Math.cos(angle) * radius
val z = center.z + Math.sin(angle) * radius
entity.teleport(Location(world, x, center.y, z))
}
}
Register this during your own plugin's onEnable, before Bosses parses configs (so subscribe to a plugin-enable ordering, or register it in a soft-depend on Bosses). Then use it in config.yml exactly like a built-in action:
Code:
abilities:
panic_teleport:
type: defensive
trigger:
type: hp_threshold
percent: 25.0
actions:
- type: teleport_random
radius: 12.0
Inside a BossAction, context.activeBoss gives you the Boss interface (config, entity, hp), and context.attacker is the Player who dealt damage — only non-null for damage-triggered abilities. context.nearbyPlayers(radius) is also available for anything AoE-flavored.
5. The Boss interface
Every Boss you get back from the API exposes:
- config — the BossConfig (display name, health, rewards, etc.)
- entity — the underlying LivingEntity
- currentHp / maxHp
- damageMap — read-only map of attacker UUID to damage dealt
- percentHp() / isDead()
- topDamagers(limit) — sorted damage ranking
This is intentionally read-only — mutation only happens through the API (damageBoss, healBoss, kill) so state stays consistent no matter who's calling it.
6. PlaceholderAPI support
Bosses hooks into PlaceholderAPI automatically if it's installed — no config needed.
General:
%bosses_active% — number of currently active bosses
%bosses_total% — number of configured boss types
%bosses_any_active% — true/false, is any boss active
%bosses_first_name% — display name of the first active boss
%bosses_first_health% — current HP of the first active boss
%bosses_first_max_health% — max HP of the first active boss
%bosses_first_percent% — HP % of the first active boss
Per-boss (replace <id> with a boss config ID, e.g. block_warden):
%bosses_<id>_active% — true/false
%bosses_<id>_name% — display name
%bosses_<id>_location% — configured location label
%bosses_<id>_health% — current HP
%bosses_<id>_max_health% — max HP
%bosses_<id>_percent% — HP percentage
%bosses_<id>_world% — spawn world
%bosses_<id>_x% / _y% / _z% — spawn coordinates
%bosses_<id>_top_damage% — highest single-player damage dealt
%bosses_<id>_top_player% — name of the top damager
%bosses_<id>_players% — number of players who've dealt damage
