PunishmentService interface
Kicks, bans and ban-wave control, running through Venus’ punishment pipeline so listeners can react.
Reach it through api.punishments(). Everything here fires the normal events — a PunishmentEvent listener sees API-initiated punishments exactly like ones a check produced, so logging and appeal integrations do not care who started it.
| Signature | Description |
|---|---|
boolean kick(User, String reason) | Kicks the user. Returns true when the platform accepted the command. |
boolean ban(User, String reason) | Permanent ban through the configured ban actions. |
boolean banwave(User, String reason) | Adds the user to the cloud ban wave immediately. |
boolean banwaveEnabled() | Whether the ban wave is currently running. |
void setBanwaveEnabled(boolean) | Starts or stops the ban wave. |
int banwaveDurationMinutes() | Default wave duration in minutes. |
void setBanwaveDurationMinutes(int) | Changes the duration used by the next wave. |
api.users().queryUserByUuid(target).ifPresent(user -> {
boolean accepted = api.punishments().ban(user, "Confirmed by staff review");
if (!accepted) {
getLogger().warning("Ban command rejected for " + user.username());
}
});Ban waves
A ban wave does not punish immediately — it queues the player and punishes everyone together when the wave closes, so cheaters cannot infer which detection caught them.banwave(user, reason) enqueues one player right now; the enabled/duration pair controls the schedule the cloud runs.
if (!api.punishments().banwaveEnabled()) {
api.punishments().setBanwaveDurationMinutes(30);
api.punishments().setBanwaveEnabled(true);
getLogger().info("Ban wave started, closes in 30 minutes");
}Kick vs the User methods
punishments().kick(user, reason) and user.kick(reason) run the same path. user.disconnect(reason) does not — it is the raw connection drop with no event and no cancellation. The details are on the User interface page.
Thresholds and actions themselves are configuration — checks.yml.