Messages and logging
Plex gives modules two services for text. MessageApi turns MiniMessage text into components and sends broadcasts.
LoggingApi writes lines to the server console and log.
Get each service from the Plex API. In your module class and in a command that extends SimplePlexCommand, call
api(). In other classes, keep a reference to your module and call module.api(). See the API overview for
more about api().
MessageApi messages = api().messages();LoggingApi logging = api().logging();MessageApi
Section titled “MessageApi”Javadoc: MessageApi
| Method | What it does |
|---|---|
messageComponent(String entry, TagResolver... placeholders) |
Reads the key entry from the Plex messages.yml and returns it as a component. Plex fills each tag from the placeholders. |
messageString(String entry) |
Returns the raw MiniMessage text of the key entry from the Plex messages.yml. Plex does not parse it. |
miniMessage(String input, TagResolver... placeholders) |
Parses your own MiniMessage text into a component. |
playerText(String input) |
Parses text that a player wrote. Plex allows only visual formatting. |
chatLine(Player player, Component message) |
Builds the public chat line of a player, with the configured chat format, prefix, and display name. It does not send the line. |
broadcast(String miniMessage) |
Parses MiniMessage text and sends it to every online player and the console. |
broadcast(Component component) |
Sends a component to every online player and the console. |
captureActionBroadcast(CommandSender sender) |
Records who may see an announcement about an action by sender. Returns an ActionBroadcast. |
sendAdminChat(String senderName, Component prefix, Component message) |
Sends a message to staff chat on this server. |
Placeholders
Section titled “Placeholders”Plex messages use named MiniMessage tags, such as <player>. Numbered placeholders such as {0} do not work in
messages. Give one TagResolver for each tag:
Placeholder.unparsed("player", name)inserts plain text. Tags in the value stay as literal text.Placeholder.component("reason", component)inserts a component that you already built.
messageComponent and messageString read only the Plex messages.yml. To read your module’s own message file, use
messageComponent on your module. That method falls back to the Plex file when your file does not have the key. See
Configuration and messages. The keys and tags of the Plex file are on the
Messages page.
If the key does not exist in the Plex messages.yml, messageComponent and messageString throw a
NullPointerException.
import dev.plex.api.message.MessageApi;import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
MessageApi messages = module.api().messages();staff.sendMessage(messages.messageComponent("bannedPlayerJoined", Placeholder.unparsed("player", bannedName)));Text that players write
Section titled “Text that players write”miniMessage and messageComponent accept every MiniMessage tag, which includes click, hover, and insertion tags. Do
not add player text to the input string. A player could add a click event that runs a command. Pass player text in a
placeholder instead.
Use playerText when a player may color their own text, for example a nickname or a report reason. It allows colors,
gradients, rainbow text, fonts, and the bold, italic, underlined, and strikethrough decorations. It keeps all other tags
as literal text. If the text has legacy & color codes, Plex reads the legacy codes instead of MiniMessage and removes
obfuscation.
MessageApi messages = module.api().messages();Component line = messages.miniMessage("<gold><reporter></gold> <gray>reported:</gray> <reason>", Placeholder.unparsed("reporter", reporter), Placeholder.component("reason", messages.playerText(reason)));staff.sendMessage(line);Chat lines
Section titled “Chat lines”chatLine gives the same line that Plex shows in public chat for that player. It uses chat.format from the Plex
config.yml. Plex calls PlayerPrefixEvent with the CHAT target while it builds the line, so prefixes from other
modules are included. See Events. Call chatLine on a thread that can read the player, for example the
command thread of that player.
Broadcasts
Section titled “Broadcasts”broadcast sends to every online player and the console.
module.api().messages().broadcast("<green>The build contest starts in 5 minutes.");ActionBroadcast
Section titled “ActionBroadcast”Javadoc: ActionBroadcast
Use an ActionBroadcast to announce a staff action, such as “Alice put out Bob”. It keeps a vanished staff member
hidden.
| Method | What it does |
|---|---|
send(Component message) |
Sends the announcement to the audience that captureActionBroadcast recorded. |
captureActionBroadcast(sender) decides the audience when you call it:
- If the sender is the console, or a player who is not vanished,
sendgoes to every online player and the console. - If the sender is a vanished player,
sendgoes to that player, the console, and the online players who can see that player at the time of the capture. Players who join later do not receive it. - If the server has no SuperVanish or PremiumVanish,
sendgoes to everyone.
Call captureActionBroadcast on the command thread of the sender, before you schedule work on another entity or region,
or start asynchronous work. You can call send from any thread, including the completion of a future. Call send
only after the action succeeds. Use one ActionBroadcast for one action.
import dev.plex.api.message.ActionBroadcast;
private Component extinguish(CommandSender sender, Player target){ // Capture on the command thread, before the work moves to the target's thread. ActionBroadcast announcement = api().messages().captureActionBroadcast(sender); Component message = api().messages().miniMessage("<aqua><actor> put out <target>.", Placeholder.unparsed("actor", sender.getName()), Placeholder.unparsed("target", target.getName())); ownTask(target.getScheduler().run(taskOwner(), task -> { target.setFireTicks(0); announcement.send(message); }, null)); return null;}Staff chat
Section titled “Staff chat”sendAdminChat sends a message to staff chat on this server. Plex formats it with the adminChatFormat message, which
has the <sender>, <prefix>, and <message> tags. Online players with the plex.adminchat permission receive it.
Plex does not send it to the console or to other servers.
Before Plex sends the message, it calls StaffChatMessageEvent with the source API. If a listener cancels the event,
Plex sends nothing. See Events.
MessageApi messages = module.api().messages();messages.sendAdminChat(reporter, messages.miniMessage("<red>[Report]"), messages.playerText(reason));LoggingApi
Section titled “LoggingApi”Javadoc: LoggingApi
LoggingApi writes to the server console and log through the Plex logger. Each line starts with a Plex label, such as
[Plex] or [Plex Error]. You can call these methods from any thread.
| Method | What it does |
|---|---|
info(String message, Object... args) |
Writes an information line with the [Plex] label. |
debug(String message, Object... args) |
Writes a line with the [Plex Debug] label, only when debug is true in the Plex config.yml. |
warn(String message, Object... args) |
Writes a warning line with the [Plex Warning] label. |
error(String message, Object... args) |
Writes an error line with the [Plex Error] label. |
Log messages use numbered placeholders. Plex replaces {0} with the first argument, {1} with the second, and so on.
Plex then parses the full line as MiniMessage, so you can add color tags.
LoggingApi log = api().logging();log.info("Loaded {0} homes in {1} ms", count, millis);log.debug("Time zone: {0}", zone);Log an exception
Section titled “Log an exception”LoggingApi has no exception parameter. If you pass an exception as an argument, Plex does not write its stack trace.
To log an exception with its stack trace, use your module logger. getLogger() on your module returns a Log4j Logger
with the name of your module. Put the exception last.
try{ homes.save();}catch (IllegalStateException ex){ getLogger().error("Could not save data/homes.yml", ex);}