Messages
plugins/AstralRanks/messages.yml holds 14 keys. Each key is kebab-case in YAML and maps, via loadEnum (AstralRanks#loadConfiguration → this.loadEnum("messages.yml", RanksMessages.class)), onto a matching SCREAMING_SNAKE_CASE constant of the RanksMessages enum (rank-not-found → RANK_NOT_FOUND, etc.). RanksMessages implements the core MessageEnum contract, so every value is deserialised straight into a ComponentWrapper — MiniMessage markup, parsed once at load time, resolving both the standard AstralCore variable tags (<info>, <success>, <error>, <primary_color>, <secondary_color>, …) and any %placeholder% found in the string. Call sites send a key with RanksMessages.KEY.message(audience[, placeholders]) or resolve it inline as a Component with .component([placeholders]); both are default methods on MessageEnum. /ranks reload re-parses the whole file (see Configuration and Commands).
The shipped defaults below are French — this page documents each key's trigger and placeholders, not a translation of the copy. Reword any value freely; only the key names and the placeholders substituted into them are load-bearing.
Default file
Rank & requirement lookups
Plain lookup-miss messages — no placeholders.
Key | Sent when |
|---|---|
| Four independent sites, all a rank id failing to resolve or a player having no next rank: the |
|
|
|
|
| The |
|
|
Requirement progress
Key | Placeholders | Sent when |
|---|---|---|
|
|
|
| — | The contributed amount pushes progress to |
requirement-progress's placeholder container is built ad hoc with three registerDirect calls on a fresh AstralPaperAPI.createPlaceholderContainer(player) — registerDirect registers a value under a bare top-level key rather than a namespace, so these resolve as plain %current%/%total%/%c%, not %requirement_current%:
Placeholder | Value |
|---|---|
|
|
|
|
|
|
How the stored progress itself is written back (shouldCountUntilFull() vs. clamping to amount()) is a requirement-type concern — see Requirements & Missions.
Unlocking a rank
Key | Placeholders | Sent when |
|---|---|---|
| — | See below — two distinct sites in |
|
| The rank's |
|
| See below — sent from |
RankService#unlock(player, configuration) sends cannot-unlock from two places:
Immediately, if
isNextRank(player, configuration.id())isfalse— this rank isn't the player's current next rank. This pathreturns right away; nothing else inunlock()runs.Inside the requirement-check loop, for the first requirement whose stored progress is below its
amount().
Both unlock-success and unlock-broadcast share one placeholder container: AstralPaperAPI.createPlaceholderContainer(player).registerPlaceholder(configuration), which registers the rank under its rank namespace (see Ranks & Progression). Their only resolved placeholder is %rank_item_name% — the chain rank → item (the rank's configured display) → name (that item's display name), not %rank_name% (the rank's own display-name field). %player_name% resolves through the standard core player-name placeholder, not anything AstralRanks registers.
unlock-broadcast is sent from two call sites:
RankService#unlock, after a successful requirement check (modulo the caveat above) — broadcast network-wide via the coreChatService#broadcastMessage(implemented by AstralChat'sPaperChatService, which both broadcasts locally and publishes the component over its messaging bus so every connected server broadcasts it too), unlessconfiguration.id()is listed inconfig.yml'signore-broadcast— see Configuration.MainCommand#onBroadcast(/ranks broadcast <rankId>, permissionastralranks.broadcast) — resends the same message with a fresh placeholder container built from the command sender, but sent only to the sender, not broadcast, as a way to preview the unlock-announcement format for a given rank. See Commands.
Quest display toggle
Key | Sent when |
|---|---|
|
|
| The same action, when the requested category already equals the player's current |
The action takes one placeholder-wrapped category argument and toggles: if playerRankData.categoryQuestsDisplay() already equals the parsed argument, it's set to null and quests-display-disabled fires; otherwise it's set to the argument and quests-display-enabled fires. There is no dedicated "off" value — toggling the same category off again is what produces null.
Quest display line template
quest-display-format is not sent to a player directly — it's the per-line template that %ranks_questsDisplay% (RanksPlaceholders, namespace ranks, case questsDisplay) resolves with, once per matching requirement, and returns as a List<Component> (capped at 5 entries) for whatever consumes that placeholder (menu lore, a scoreboard line, etc.). See Placeholders for the full %ranks_*% catalogue.
Key | Placeholders | Value |
|---|---|---|
|
|
|
Resolution requires a Player context and yields null (nothing rendered) if any of the following hold: the player has no next rank (RankService#getNextRank returns null); or their categoryQuestsDisplay is null — i.e. the toggle above is off. If a category is enabled, the placeholder iterates the next rank's requirements, skips any whose category doesn't match the enabled one (unless it's "all", case-insensitive), skips any already at current >= total, and renders the rest through quest-display-format — capped at the first 5. Note: unlike most other lookups in this plugin, a missing PlayerRankData here throws IllegalStateException rather than failing gracefully to a message.
Miscellaneous
Key | Sent when |
|---|---|
| The sole fallback branch of |
Where to go next
Ranks & Progression — the unlock flow and the
rankplaceholder namespace these messages draw from.Requirements & Missions — requirement
types and category/reward payout behindrequirement-*keys.Placeholders — the full
%ranks_*%/%rank_*%/%requirement_*%catalogue, including%ranks_questsDisplay%.Developer API —
unlock-rank,update-rank-requirement,set-displayed-ranks-quests.Configuration —
config.yml'signore-broadcastand the full reload order.Commands —
/ranks broadcastand/mission, the two commands that surface these messages directly.