Astral Realms Documentation Help

Private Messages

Private messages are cross-server: the sender's request is routed through RabbitMQ to the recipient's server, the response comes back the same way. The flow is fronted by PrivateMessageService and the underlying packets are PrivateMessageRequest/PrivateMessageResponse.

Sending

/msg <player> <message>

Aliases: /message, /m, /t.

The sender and recipient both see the message rendered with the formats.private-messages template from config.yml. The format receives:

Variable

Value

%sender_name%

Sender's display name.

%target_name%

Recipient's display name.

<chat>

The message body.

Error responses (in order of priority):

Condition

Message key

Recipient is the sender

cannot-message-yourself

Recipient is unknown (offline anywhere on the network)

player-not-found

Recipient has /togglepm off

private-message-recipient-disabled

Sender is ignored by the recipient

ignore-recipient

Anything else

private-message-error

Every successful conversation is persisted to the private_messages table.

Replying

/reply <message> /r <message>

Replies to the last person you exchanged a PM with. If no conversation has happened (or the cached target has since gone offline), the player receives no-message-to-reply-to or reply-player-offline.

Toggling private messages

/togglepm /tpm

Toggles PlayerChatData.privateMessagesEnabled. The persistent flag is checked at every incoming /msg: when off, the sender gets private-message-recipient-disabled and nothing is delivered.

Confirmation messages: private-message-enabled/private-message-disabled.

Ignoring

/ignore [player] /unignore <player>
  • /ignore with no argument opens a menu of currently ignored players.

  • /ignore <player> adds the player to the ignore list (database + Redis cache).

  • /unignore <player> removes the entry.

  • /ignore rejects self-targeting with ignore-self.

Ignore state is preloaded into Redis on every join by IgnoreListener so the PM pipeline can check it synchronously without a DB round-trip.

The unignore-player AstralCore action (see Actions) lets menus remove an entry by UUID without exposing the command.

Social spy

/socialspy /ss

Toggles whether the staff member receives a copy of every private message sent on the network. Permissions are pulled from config.yml — defaults are chat.socialspy (required to toggle and receive) and chat.socialspy.bypass (worn by players who must never be spied on).

Spy output uses the social-spy.format template with:

Variable

Value

%sender%

Sender display name.

%recipient%

Recipient display name.

%message%

The message body.

Confirmation messages: social-spy-enabled/social-spy-disabled.

Cross-server topology

Sender server Recipient server ───────────── ──────────────── /msg ──► PrivateMessageService │ │ PrivateMessageRequest (RabbitMQ exchange) ├────────────────────────────────────► │ │ PrivateMessageService │ ├── check toggle / ignore │ ├── render component │ ├── deliver to recipient │ └── reply │ │ PrivateMessageResponse (status) ◄────────────────────────────────────┤ │ ├── render component for sender ├── deliver to sender └── fan out to social-spy receivers

The response status enum carries SUCCESS, USER_MESSAGING_DISABLED, USER_NOT_FOUND, or IGNORED, which the sender side maps to the appropriate message key.

Last modified: 25 July 2026