Astral Realms Documentation Help

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

database.properties

all

JDBC connection.

messages.yml

velocity, paper

Player- and staff-facing text.

limits.yml

velocity

Duration ceilings per staff tier.

warnings.yml

velocity

How long a warning stands.

discord.yml

velocity

Webhooks.

mute.yml

paper

Which commands a mute blocks.

display.yml

paper

Per-type GUI icons.

config.yml

master

Whether the HTTP API exposes addresses.

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:

jdbcUrl=jdbc:mariadb://localhost:3306/punishments?useSSL=false driverClassName=org.mariadb.jdbc.Driver dataSource.user=testuser dataSource.password=test623 poolName=AstralPunishments

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

target-muted/target-muted-broadcast

/mute — operator feedback / network broadcast.

target-unmuted/target-unmuted-broadcast/target-not-muted

/unmute.

target-warned

/warn — operator feedback.

player-warned

/warn — shown to the target, now or on their next login (%reason%, %source%).

target-unwarned/target-unwarned-broadcast/target-not-warned

/unwarn.

target-kicked

/kick — operator feedback, sent once the disconnect succeeds.

player-kicked/player-kicked-broadcast

/kick — screen shown to the disconnected player / network broadcast.

player-banned

Screen shown to a banned player, both on issue and at the BanListener login gate.

target-banned/target-banned-broadcast

/ban — operator feedback / network broadcast.

target-unbanned/target-unbanned-broadcast/target-not-banned

/unban.

player-ipbanned

Screen shown to an IP-banned player, both on issue and at the BanListener login gate.

target-ipbanned/target-ipbanned-broadcast

/ipban — operator feedback / network broadcast.

target-no-ip

/ipban when neither a live connection nor ip_history has an address for the target.

target-exempt

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.

duration-too-long

A ban / IP ban / mute longer than the issuer's ceiling (%max%).

unexpected-error

Any command whose async pipeline fails (database, messaging).

player-not-online

/kick when the target isn't currently connected to any backend.

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

no-history

/history when the target has no punishment rows at all.

no-alts

/alts when no account shares an address with the target.

no-ip-history

The address section when the account has no recorded address.

no-results

/banlist, /mutelist, /warnlist, /staffhistory when the listing is empty.

chat-muted

A muted player tries to chat (%punishment_reason%, %punishment_remaining%).

command-muted

A muted player runs a command listed in mute.yml.

no-permission

Pardon action, when the clicking player lacks the type-specific unban/unmute node.

pardon-success

Pardon action, after a successful pardon.

already-pardoned

Pardon action, if the punishment was pardoned by someone else between opening the menu and clicking confirm.

cannot-pardon

Pardon action, for a KICK/WARN punishment (not a liftable type).

invalid-duration

/history <player> <duration> when the duration filter fails to parse.

error-occurred

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).

default-max-duration: "" # ceiling for staff holding no tier; empty = no cap tiers: - permission: "punishments.limit.helper" max-duration: "7d" - permission: "punishments.limit.moderator" max-duration: "30d" - permission: "punishments.limit.admin" max-duration: "" # no ceiling

Key

Type

Default

Description

default-max-duration

String (duration)

""

Ceiling for staff who hold no tier. Blank or unparseable = no cap.

tiers

List

[]

One entry per ceiling.

tiers[].permission

String

—

The node that grants this tier.

tiers[].max-duration

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.

default-duration: "" # e.g. "90d"

Key

Type

Default

Description

default-duration

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.

enabled: false url: "" username: "Punishments" avatar-url: "" thumbnail-url: "" # supports %uuid% and %name% events: ban: enabled: true color: "#E74C3C" title: "Joueur banni" # ipban, mute, kick, warn, unban, unmute, unwarn

Key

Type

Default

Description

enabled

boolean

false

Master switch. Nothing is posted unless this and a URL are set.

url

String

""

The webhook every event posts to unless it overrides it.

username

String

"Punishments"

What the webhook posts as. Blank uses the Discord-side name.

avatar-url

String

""

Override avatar. Blank uses the Discord-side one.

thumbnail-url

String

""

Head shown beside the embed, for a punishment against an account. Supports %uuid% and %name%. Blank for none.

events.<event>.enabled

boolean

true

Whether this event is posted.

events.<event>.url

String

the shared url

A webhook of its own — e.g. bans and mutes in different channels.

events.<event>.color

String

per event

#RRGGBB, RRGGBB, 0x… or a plain decimal. Unreadable falls back to the default.

events.<event>.title

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).

blocked-commands: - "msg" - "m" - "r" - "me" - "say"

Key

Type

Description

blocked-commands

List<String>

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.

icons: BAN: material: "IRON_BARS" name: "<bold><red>Bannissement" IPBAN: material: "ANVIL" name: "<bold><red>Bannissement IP" MUTE: material: "BOOK" name: "<bold><gold>Réduction au silence" KICK: material: "LEATHER_BOOTS" name: "<bold><yellow>Expulsion" WARN: material: "PAPER" name: "<bold><yellow>Avertissement"

Key

Type

Description

icons

Map<PunishmentType, ItemStackWrapper>

One entry required per PunishmentType value (BAN, IPBAN, MUTE, KICK, WARN) — a missing entry resolves to null and the history row's copy-from has nothing to copy.

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.

Last modified: 25 September 2026