Configuration
AstralPunishments ships separate config files per module — velocity/, paper/ and master/ each get their own copy, loaded independently on onEnable/loadConfiguration(). They point at the same database and schema, so every module reads what the others wrote.
File | Module | Covers |
|---|---|---|
| all | |
| velocity, paper | |
| velocity | |
| velocity | |
| velocity | |
| paper | |
| paper | |
| master |
database.properties
Both modules copy and load a standard HikariCP JDBC properties file — see the AstralCore database docs for the field reference. The shipped default in both modules points at the same schema:
The tables it expects (punishments, ip_history) are defined in velocity/src/main/resources/schema.sql — see Overview → Data model for the shape.
messages.yml (velocity)
Loaded via loadEnum("messages.yml", PunishmentMessages.class) into the velocity PunishmentMessages enum. Every key is a MiniMessage string; %target_name%, %reason%, %source% and %duration% are available wherever the corresponding punishment supplies them (see the command feedback table below).
Key | Used by |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| Screen shown to a banned player, both on issue and at the |
|
|
|
|
| Screen shown to an IP-banned player, both on issue and at the |
|
|
|
|
| Any punishment refused because the target's immunity is at or above the issuer's — including a bare-address ban where any account on the address is protected. |
| A ban / IP ban / mute longer than the issuer's ceiling ( |
| Any command whose async pipeline fails (database, messaging). |
|
|
messages.yml (paper)
Loaded the same way on the paper side, backing the history GUI and pardon action. Both files ship in French and are per-server, freely re-translatable.
Key | Used by |
|---|---|
|
|
|
|
| The address section when the account has no recorded address. |
|
|
| A muted player tries to chat ( |
| A muted player runs a command listed in |
| Pardon action, when the clicking player lacks the type-specific unban/unmute node. |
| Pardon action, after a successful pardon. |
| Pardon action, if the punishment was pardoned by someone else between opening the menu and clicking confirm. |
| Pardon action, for a |
|
|
| Any async failure (database lookup, menu open). |
limits.yml
How long a punishment each staff member may issue. Caps apply to BAN, IPBAN and MUTE only — a kick has no duration, and a warning is a record rather than a restriction. The console is never capped, and permanent counts as longer than any ceiling, so an omitted duration cannot sidestep a cap.
Every tier a staff member holds raises their ceiling: their cap is the longest duration across the tiers they hold, and a tier with no max-duration lifts the cap entirely (permanent punishments allowed).
Key | Type | Default | Description |
|---|---|---|---|
| String (duration) |
| Ceiling for staff who hold no tier. Blank or unparseable = no cap. |
| List |
| One entry per ceiling. |
| String | — | The node that grants this tier. |
| String (duration) | — | The ceiling. Blank = uncapped. |
Nothing is capped out of the box: limits are opt-in and change nothing until a tier is added. A configured cap that is exceeded answers duration-too-long with %max%. Durations use the same syntax as the commands.
warnings.yml
How long a warning stands.
Key | Type | Default | Description |
|---|---|---|---|
| String (duration) |
| Applied to a warning issued without one. Blank or unparseable = the warning stands permanently. |
Leaving it empty is how warnings behaved before they could expire, so an upgrade changes nothing until it is set. Setting it is what stops an old warning counting against a player forever — and what keeps /warnlist bounded, since that listing shows warnings still standing and is capped at 500 rows. Staff override it per warning: /warn <player> 7d <reason>.
discord.yml
Every punishment issued or lifted on the proxy is posted to Discord as an embed — the staff-channel counterpart of the in-game broadcast. Off until a webhook URL is configured: this is the one thing here that talks to a third party, so it does nothing at all on a fresh install.
Key | Type | Default | Description |
|---|---|---|---|
| boolean |
| Master switch. Nothing is posted unless this and a URL are set. |
| String |
| The webhook every event posts to unless it overrides it. |
| String |
| What the webhook posts as. Blank uses the Discord-side name. |
| String |
| Override avatar. Blank uses the Discord-side one. |
| String |
| Head shown beside the embed, for a punishment against an account. Supports |
| boolean |
| Whether this event is posted. |
| String | the shared | A webhook of its own — e.g. bans and mutes in different channels. |
| String | per event |
|
| String | per event | The embed title. |
The eight events are ban, ipban, mute, kick, warn, unban, unmute, unwarn — one per staff action rather than one per punishment type, since a ban and the lifting of that ban are the same type but two very different things to read in a staff channel. An event left out of the file uses its defaults and is posted, so events added in a later version start working on upgrade rather than staying quietly off.
Silent (-s) punishments are posted too, marked (silencieuse) in the title. Delivery is best-effort and entirely off the punishment path: a webhook that is slow, rate-limited or gone never holds up a ban — failures are logged and the embed is dropped.
mute.yml
Which commands a mute blocks, on top of normal chat (which is always blocked).
Key | Type | Description |
|---|---|---|
|
| Bare command names, no leading slash. |
Matching is case-insensitive and ignores any plugin namespace, so msg also covers /MSG and /astralchat:msg. Aliases are not implied — msg does not cover m; list every alias you want blocked. The shipped file covers AstralChat's private-message and channel commands plus the vanilla /me, /say, /teammsg. The list is normalised once at load time, so the check on every command a player runs is a plain set lookup. See Overview → Mute enforcement.
display.yml
Maps each PunishmentType to the ItemStackWrapper (material / name / lore) used as its icon in the history GUI — loaded into PunishmentDisplayConfiguration (Map<PunishmentType, ItemStackWrapper>). The history rows copy-from this icon and append their own per-punishment lore.
Key | Type | Description |
|---|---|---|
|
| One entry required per |
Menu blueprints
Seven blueprints under menus/punishments/ are copied out of the jar on first load (copyResource, since the menus/ folder isn't auto-extracted) and loaded by MenuService#load(): lookup.yml, history.yml, detail.yml, confirm-pardon.yml, alts.yml, iphistory.yml and list.yml. See Staff menus for what opens each one, and Punishment History GUI for the history → detail → pardon flow.