Chat

In-game text chat for player communication.

Channels

Channel Scope Prefix Color
Global All connected players [G] white (default)
Local Players orbiting the same reference body [L] cyan
Direct Player-to-player private messages [D] yellow

Channel Behavior

Global: Messages sent to all connected players. Default channel.

Local: Messages sent to players whose ship orbits the same reference body as the sender. The api-gateway looks up each player’s ship reference body from the latest tick state. If the sender’s reference body is unknown, the message falls back to global.

Direct: Messages sent to a specific player by player_id. Both sender and recipient see the message. If the target player is offline, the server returns error E030.

Channel Selection

The chat window includes a channel selector dropdown (Global / Local / Direct). When Direct is selected, a recipient input appears for entering the target player name. The client resolves the player name to ID using the players list from the welcome message.

Message Format

Client → Server (chat_send)

Field Type Required Description
type string yes "chat_send"
message string yes Message text (1–256 chars)
channel string no "global" (default), "local", or "direct"
ref_body string no Sender’s reference body name (required when channel is "local")
target_id string no Recipient player_id (required when channel is "direct")

Server → Client (chat_message)

Field Type Description
type string "chat_message"
player_id uuid Sender’s player ID
username string Sender’s display name
message string Message text (1–256 chars)
channel string "global", "local", or "direct"
timestamp number Server Unix time in seconds (epoch)

Constraints

Parameter Value
Max message length 256 characters
Rate limit 5 messages per second per player (shared across all channels)
Rate limit window 1.0 second (sliding)
Max displayed messages 200 (oldest removed, per window — not per channel)

XSS Prevention

All user-supplied content (username, message) is rendered via textContent — never innerHTML. This prevents script injection without requiring sanitization libraries.

Unread Indicator

When the chat window is closed and a new message arrives, a pulsing red badge appears on the chat window’s position in the View menu. The badge clears when the window is opened. All channels share a single unread counter.

Keyboard Shortcut

Shift+C toggles the chat window in both cockpit and map views.

Chat Window

  • Floating/draggable window (same pattern as Ship Status, Orbit Diagram, etc.)
  • Default position: bottom-right (bottom: 60px; right: 20px)
  • Dimensions: 350px wide, 300px tall
  • Message list scrolls; auto-scroll when near bottom (within 50px)
  • Channel selector dropdown above the input row
  • Input row: text input + Send button
  • When Direct channel is selected, a recipient text input appears between the channel selector and message input
  • Enter sends the message
  • stopPropagation() on input keydown/keyup prevents ship controls while typing
  • Messages are color-coded by channel (see Channels table above)
  • Channel prefix ([G], [L], [D]) appears before the sender name

Error Handling

Condition Error Code User Feedback
Rate limited E018 Status bar message “Rate limit exceeded”
Message too long E019 Status bar message “Message too long”
Empty message E020 Blocked client-side (no send)
Invalid channel E026 Status bar message “Invalid channel”
Direct target not found E030 Status bar message “Player not found”
Direct target offline E030 Status bar message “Player not online”

Server-Side Routing

Local Channel Routing

When a chat_send with channel: "local" arrives:

  1. Read ref_body from the message (client sends its current reference body name)
  2. Store ref_body in the connection’s cached state (_player_ref_bodies[player_id])
  3. For each connected player, check if their cached ref_body matches the sender’s
  4. Send the chat_message only to matching players (including sender)
  5. If ref_body is missing, fall back to global broadcast

Performance: No Redis queries or SOI computation needed. The client already computes its reference body for the orbital elements display. The server caches each player’s last-known reference body from local chat messages (updated whenever they send a local message).

Direct Channel Routing

When a chat_send with channel: "direct" arrives:

  1. Look up target_id in _connections dict
  2. If not found (offline), return error E030
  3. Send the chat_message to both sender and recipient

Back to top

Galaxy — Kubernetes-based multiplayer space game

This site uses Just the Docs, a documentation theme for Jekyll.