Astral Realms Documentation Help

Messages

plugins/AstralRanks/messages.yml holds 14 keys. Each key is kebab-case in YAML and maps, via loadEnum (AstralRanks#loadConfigurationthis.loadEnum("messages.yml", RanksMessages.class)), onto a matching SCREAMING_SNAKE_CASE constant of the RanksMessages enum (rank-not-foundRANK_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 rank-not-found: "<info>Rang non trouvé." # Requirements requirement-not-found: "<info>Pré-requis non trouvé." requirement-already-completed: "<info>Pré-requis déjà complété." requirement-take-error: "<error>Erreur pendant la dépôt du pré-requis." requirement-no-progress: "<info>Vous n'avez pas le pré-requis." requirement-progress: "<info>Vous êtes à %current%/%total% sur ce pré-requis." requirement-completed: "<success>Vous avez complété ce pré-requis !" # unlock cannot-unlock: "<error>Vous devez finir les missions avant d'obtenir le rang." unlock-success: "<success>Vous êtes maintenant %rank_item_name%." unlock-broadcast: "<newline><#267ad9><bold>➤ <#26d971>%player_name% <#267ad9>a débloqué le rang <#26d971>%rank_item_name% !<newline>" # Display quests-display-enabled: "<success>Affichage des pré-requis activé." quests-display-disabled: "<success>Affichage des pré-requis désactivé." quest-display-format: "%name% </bold><secondary_color>%current%<gray>/<secondary_color>%total%" # Miscellaneous unexpected-error: "An unexpected error occurred. Please try again later."

Rank & requirement lookups

Plain lookup-miss messages — no placeholders.

Key

Sent when

rank-not-found

Four independent sites, all a rank id failing to resolve or a player having no next rank: the unlock-rank and update-rank-requirement actions when their rank-id argument doesn't match a loaded RankConfiguration; /mission (no-arg) and /mission <category> when RankService#getNextRank returns null for the player — i.e. they're already past the last rank in the chain (see Ranks & Progression).

requirement-not-found

RankService#updateRequirement (driven by update-rank-requirement), on any of three conditions: the categoryId argument doesn't match an entry in categories.yml; no requirement in the rank matches both that category and the requirementId argument; or the player's PlayerRankData isn't loaded (SyncAPI.findData empty) — this third case reuses requirement-not-found rather than unexpected-error, unlike the equivalent missing-snapshot check in set-displayed-ranks-quests (see below).

requirement-already-completed

RankService#updateRequirement: the requirement's stored progress is already >= amount() before RankRequirement#take is even called.

requirement-take-error

The CompletableFuture returned by RankRequirement#take completes exceptionally.

requirement-no-progress

take() completes normally but resolves to 0 — the player had nothing to contribute to this requirement at the time (requirement-type-specific; see Requirements & Missions).

Requirement progress

Key

Placeholders

Sent when

requirement-progress

%current%, %total% (plus %c%, registered but unused by the shipped template)

take() contributed a non-zero amount, but current + amount is still below the requirement's amount() — progress advanced without completing it.

requirement-completed

The contributed amount pushes progress to >= amount() for the first time on this take() call. Sent before the category-completion / reward check that follows in the same callback.

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

%current%

current + amount — the player's new progress total after this contribution.

%total%

requirement.amount() — the requirement's target.

%c%

amount() - (current + amount) — the amount still needed to finish. Registered on every send, but the shipped requirement-progress string only uses %current%/%total%; %c% is available if you customise the message to show a "remaining" figure instead.

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

cannot-unlock

See below — two distinct sites in RankService#unlock.

unlock-success

%rank_item_name%

The rank's actions ran without throwing, on the next server tick after unlock() accepted the attempt.

unlock-broadcast

%player_name%, %rank_item_name%

See below — sent from RankService#unlock (network broadcast) and separately from /ranks broadcast (sender-only preview).

RankService#unlock(player, configuration) sends cannot-unlock from two places:

  1. Immediately, if isNextRank(player, configuration.id()) is false — this rank isn't the player's current next rank. This path returns right away; nothing else in unlock() runs.

  2. 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 rankitem (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 core ChatService#broadcastMessage (implemented by AstralChat's PaperChatService, which both broadcasts locally and publishes the component over its messaging bus so every connected server broadcasts it too), unless configuration.id() is listed in config.yml's ignore-broadcast — see Configuration.

  • MainCommand#onBroadcast (/ranks broadcast <rankId>, permission astralranks.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

quests-display-enabled

set-displayed-ranks-quests (SetDisplayedQuestsCategoryAction) sets the player's PlayerRankData#categoryQuestsDisplay to a new category (any string, including the special value "all").

quests-display-disabled

The same action, when the requested category already equals the player's current categoryQuestsDisplay — it's cleared back to null instead.

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

quest-display-format

%name%, %current%, %total%

%name% is the matching requirement's display-item name (its configured ItemStackWrapper name:, already resolved to a Component — spliced in directly, not re-parsed). %current%/%total% are that requirement's progress, same semantics as requirement-progress but read straight from PlayerRankData rather than a take() result.

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

unexpected-error

The sole fallback branch of set-displayed-ranks-quests's ifPresentOrElse — sent when SyncAPI.findData(player, PlayerRankData.class) returns empty for the executor, i.e. their rank snapshot isn't loaded. Contrast with RankService#updateRequirement, which sends requirement-not-found for the same missing-snapshot condition — the two flows don't agree on which key covers it.

Where to go next

  • Ranks & Progression — the unlock flow and the rank placeholder namespace these messages draw from.

  • Requirements & Missions — requirement types and category/reward payout behind requirement-* keys.

  • Placeholders — the full %ranks_*%/%rank_*%/%requirement_*% catalogue, including %ranks_questsDisplay%.

  • Developer APIunlock-rank, update-rank-requirement, set-displayed-ranks-quests.

  • Configurationconfig.yml's ignore-broadcast and the full reload order.

  • Commands/ranks broadcast and /mission, the two commands that surface these messages directly.

Last modified: 25 July 2026