Punishments
Network-wide bans, mutes, kicks and warns that survive reconnects and server transfers. Issue once, enforced everywhere, by name even when a player is offline.
A punishment applies across your whole network and persists through reconnects
and server transfers. You issue it once; every server enforces it, and it follows
the player wherever they try to go. The network is derived from your API key, so
there is no networkId to pass and nothing to sync between boxes yourself.
If you run the built-in punishments module, enforcement is already wired: bans refuse the reconnect, mutes are pushed to the player’s current server live over the event stream, and kicks take effect immediately. The SDK below is how you issue and lift punishments from your own commands, GUIs or tooling.
The four types
| Type | What it does |
|---|---|
BAN | blocks the player from joining any server on the network |
MUTE | blocks chat network-wide; pushed live to their current server |
KICK | removes them from their current server once |
WARN | records a warning on their history, no enforcement |
Every type takes a durationMs: pass null for permanent, or a millisecond
duration for a temp-ban / temp-mute. The ipBased flag also pins the punishment to
the player’s last known IP, so a ban evasion under a new name still bounces.
Issue a punishment
createPunishment is the core call. Give it the target, a type, a reason, an
optional duration, the ipBased flag, and who issued it (for the audit trail).
It’s a network call, so it’s async.
// Ban a player you can see, permanently (durationMs = null).
hive.punishments().createPunishment(
target.uuid(), target.name(), PunishmentType.BAN,
"Cheating", null, false, mod.uuid(), mod.name());
// A 30-minute mute is the same call with a duration.
hive.punishments().createPunishment(
target.uuid(), target.name(), PunishmentType.MUTE,
"Spam", Duration.ofMinutes(30).toMillis(), false, mod.uuid(), mod.name()); Punish someone offline, by name
You don’t need the player online or their UUID to hand a punishment out. Ban by
name and the hub resolves the identity network-wide; ipBased extends it to their
last known address.
// Ban someone who isn't online, by name - resolved network-wide.
hive.punishments().createPunishmentByName(
"Griefer123", PunishmentType.BAN, "Raiding", null,
/* ipBased */ true, mod.uuid(), mod.name()); There’s also createIpOnlyPunishment(ip, …) for blocking an address directly, with
no player attached.
Look up and lift
Read what’s on a player, then remove it. Queries take an activeOnly flag so you
can show either the live record or the full history.
// Look up what's active, then lift it.
hive.punishments().queryByName("Griefer123", /* activeOnly */ true)
.thenAccept(active -> { /* show the operator what's on record */ });
hive.punishments().unbanByName("Griefer123", /* alsoUnbanLastIp */ true,
mod.uuid(), mod.name(), "Appeal accepted"); | Call | What it does |
|---|---|
queryForPlayer(uuid, activeOnly) | punishments on a UUID |
queryByName(name, activeOnly) | punishments on a name, resolved network-wide |
historyByName(name, limit, offset) | paged full history for an audit view |
removePunishment(id, actor, …) | lift a single punishment by its id |
unbanByName(name, alsoUnbanLastIp, …) | lift active bans on a name, optionally the IP too |
unbanIp(ip, …) | lift an IP-level ban |
Every issue and lift records who did it, so the player’s history is a complete, attributable trail.
From the dashboard
Operators can review and lift a player’s punishments from the dashboard, and every action surfaces as an activity event on the player, next to joins, server switches and data changes.
Current limits
Shipped narrow and honest. Today that means:
- No appeals workflow - you can query and lift, but there’s no built-in player-facing appeal queue yet.
- Reason templates and presets aren’t built; reasons are free text.
Need an appeals API or a punishment webhook? Ask us - we answer fast.