BlazeBans API/Reference
Recipes
Short, complete answers to the things people build most. Each assumes `this.blazeBans` holds the API and `this.plugin` is your plugin.
Check whether a player is muted
this.blazeBans.punishments().isMuted(player.getName(), player.getUniqueId())
.thenAccept(muted -> {
if (!muted) {
return;
}
player.getScheduler().run(this.plugin, task ->
player.sendMessage(Component.text("You are muted.")), null);
});Show a mute reason and remaining time
this.blazeBans.punishments().activeMute(player.getName(), player.getUniqueId())
.thenAccept(found -> found.ifPresent(punishment -> {
String remaining = punishment.permanent()
? "permanently"
: "for " + format(Duration.between(Instant.now(), punishment.expiresAt()));
player.getScheduler().run(this.plugin, task -> player.sendMessage(
Component.text("Muted " + remaining + ": " + punishment.reason())), null);
}));
private static String format(Duration duration) {
if (duration.isNegative()) {
return "0m";
}
long days = duration.toDays();
if (days > 0) {
return days + "d " + duration.toHoursPart() + "h";
}
long hours = duration.toHours();
return hours > 0 ? hours + "h " + duration.toMinutesPart() + "m" : duration.toMinutes() + "m";
}Count a player's active warnings
this.blazeBans.punishments().history(playerName)
.thenApply(records -> records.stream()
.filter(record -> record.type() == PunishmentType.WARN)
.filter(Punishment::active)
.count())
.thenAccept(count -> getLogger().info(playerName + " has " + count + " active warnings"));Block a feature while a player has an active warning
@EventHandler
public void onUseFeature(SomeEvent event) {
Player player = event.getPlayer();
this.blazeBans.punishments()
.activePunishment(PunishmentType.WARN, player.getName(), player.getUniqueId())
.thenAccept(warning -> warning.ifPresent(punishment ->
player.getScheduler().run(this.plugin, task ->
player.sendMessage(Component.text("Unavailable while you have an active warning.")),
null)));
}Note this cannot cancel the event: by the time the answer arrives, the event has already resolved. To actually gate something, keep a cached state updated from the punishment events and read that synchronously.
Keep a cached mute state
private final Map<UUID, Boolean> muted = new ConcurrentHashMap<>();
@EventHandler
public void onJoin(PlayerJoinEvent event) {
UUID uuid = event.getPlayer().getUniqueId();
this.blazeBans.punishments().isMuted(event.getPlayer().getName(), uuid)
.thenAccept(state -> this.muted.put(uuid, state));
}
@EventHandler
public void onQuit(PlayerQuitEvent event) {
this.muted.remove(event.getPlayer().getUniqueId());
}
@EventHandler
public void onPunishmentCreated(BlazeBansPunishmentCreatedEvent event) {
UUID uuid = event.punishment().targetUuid();
if (uuid != null && isMuteType(event.punishment().type())) {
this.muted.put(uuid, true);
}
}
@EventHandler
public void onPunishmentRevoked(BlazeBansPunishmentRevokedEvent event) {
UUID uuid = event.punishment().targetUuid();
if (uuid != null && isMuteType(event.punishment().type())) {
this.muted.put(uuid, false);
}
}
private static boolean isMuteType(PunishmentType type) {
return type == PunishmentType.MUTE || type == PunishmentType.IP_MUTE;
}Now this.muted.getOrDefault(uuid, false) is safe to read synchronously, which is what lets you cancel an event on it.
This misses expiry, since nothing fires when a mute lapses. Either re-check periodically or store the expiry instant instead of a boolean.
Ban a player from your own code
PunishmentCreateRequest request = new PunishmentCreateRequest(
PunishmentType.BAN,
target.getName(),
target.getUniqueId(),
ipOf(target),
"MyPlugin",
null,
Duration.ofDays(7),
"Automated: exploit detected",
"",
"server",
this.serverId,
false
);
this.blazeBans.punishments().createPunishment(request)
.whenComplete((created, error) -> {
if (error != null) {
getLogger().warning("Ban failed: " + error.getMessage());
return;
}
created.ifPresentOrElse(
punishment -> getLogger().info("Created " + punishment.id()),
() -> getLogger().info("Another plugin cancelled the ban.")
);
});
private static String ipOf(Player player) {
return player.getAddress() == null
? ""
: player.getAddress().getAddress().getHostAddress();
}Unban when an appeal is accepted
public void acceptAppeal(String punishmentId, String staffName) {
this.blazeBans.punishments()
.revokePunishment(punishmentId, staffName, "Appeal accepted")
.whenComplete((revoked, error) -> {
if (error != null) {
getLogger().warning("Revoke failed: " + error.getMessage());
return;
}
revoked.ifPresentOrElse(
punishment -> getLogger().info("Revoked " + punishment.id()),
() -> getLogger().info("No active punishment with that ID.")
);
});
}Crediting the real staff member rather than your plugin keeps /staffhistory honest.
Stop specific players being banned
@EventHandler(priority = EventPriority.HIGHEST)
public void onPunishmentCreate(BlazeBansPunishmentCreateEvent event) {
if (event.request().type() != PunishmentType.BAN) {
return;
}
if (this.protectedNames.contains(event.request().targetName().toLowerCase(Locale.ROOT))) {
event.setCancelled(true);
}
}BlazeBans' own exempt.players does this in config, which is usually better. Use code when the condition is something only your plugin knows.
Force a minimum ban duration
@EventHandler(priority = EventPriority.LOW)
public void onPunishmentCreate(BlazeBansPunishmentCreateEvent event) {
if (event.request().type() != PunishmentType.BAN) {
return;
}
Duration minimum = Duration.ofDays(1);
Duration current = event.request().duration();
// Duration.ZERO means permanent, which is already longer than any minimum.
if (!current.isZero() && current.compareTo(minimum) < 0) {
event.request().duration(minimum);
}
}Forward every punishment to your own system
@EventHandler(ignoreCancelled = true)
public void onPunishmentCreated(BlazeBansPunishmentCreatedEvent event) {
Punishment punishment = event.punishment();
CompletableFuture.runAsync(() -> postToMyApi(
punishment.id(),
punishment.type().name(),
punishment.targetName(),
punishment.staffName(),
punishment.reason()
));
}Do the network call off the event thread. ignoreCancelled keeps punishments another plugin suppressed out of your feed.
Find every ban issued in the last week
this.blazeBans.punishments().activeBans()
.thenApply(bans -> bans.stream()
.filter(ban -> ban.createdAt().isAfter(Instant.now().minus(Duration.ofDays(7))))
.toList())
.thenAccept(recent -> getLogger().info(recent.size() + " bans this week"));Look up a punishment from a command argument
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length < 1) {
return false;
}
// Both ABC123 and #ABC123 resolve.
this.blazeBans.punishments().punishmentById(args[0])
.thenAccept(found -> {
String reply = found
.map(punishment -> punishment.targetName() + ": " + punishment.reason()
+ " (" + punishment.status() + ")")
.orElse("No punishment with that ID.");
Bukkit.getGlobalRegionScheduler().run(this.plugin, task ->
sender.sendMessage(reply));
});
return true;
}Detect a linked banned account on join
The complete version is in Players and alts.
Delay a ban to play an effect
The complete version is in Enforcement and exemptions.

