← All Workshops

MudEngine Part 6: Multiplayer

Congratulations!

You just built a multiplayer MUD engine with real-time WebSocket communication!

What we achieved:

  • Fullstack Dioxus — one codebase, two targets (server + WASM), all in Rust
  • WebSocket endpoint — a #[get] server function that upgrades HTTP to a persistent bidirectional connection
  • Authoritative server — movement validation prevents wall-walking; the server is the single source of truth
  • Real-time broadcastingtokio::sync::broadcast fans out every player action to all connected clients
  • Reactive client UIuse_websocket + use_future react to incoming messages and update the grid/sidebar instantly
  • Player lifecycle — join (name entry), move (D-pad, clickable rooms, keyboard), leave (disconnect detection)

Architecture recap

┌──────────────┐     WebSocket     ┌──────────────────┐
│  Browser A   │ ◄──────────────► │  Axum Server      │
│  - Alice     │                   │  - #[get] handler │
│  - use_ws     │                   │  - PlayerManager  │
│  - grid+dpad  │                   │  - broadcast      │
└──────────────┘                   │  - room exits     │
                                   └──────────────────┘
┌──────────────┐     WebSocket            ▲
│  Browser B   │ ◄────────────────────────┘
│  - Bob       │
│  - use_ws     │
│  - grid+dpad  │
└──────────────┘

Every player action follows the same path: client → server → validate → broadcast → all clients update. No client trusts its own input for game state — the server decides and tells everyone.

What's next?

The dungeon keeps growing! Future parts could explore:

  • Persistent world — store player positions and room state in a database (SQLite via sqlx)
  • Chat — add a chat panel where players can send messages to each other
  • Combat — monsters in rooms, attack commands, health tracking
  • Inventory — items the player can pick up and carry between rooms
  • Authentication — sessions and login so players keep their name across page reloads
  • Room state — locks, doors, torches that can be lit or extinguished

The MUD lives! 🏰⚔️

📚 What we learned
ConceptHow we used it
#[get] server functionAxum endpoint that handles WebSocket upgrades with WebSocketOptions
Websocket<In, Out>Strongly-typed WebSocket with JSON serialization of custom enums
use_websocketDioxus hook that reactively manages a WebSocket connection
use_futureLong-lived async loop for receiving WebSocket messages
tokio::select!Multiplexing between client messages and broadcast messages
tokio::sync::broadcastFan-out channel that delivers every message to all subscribers
cfg(feature = "server")Conditional compilation — server state only exists in the server binary
D-pad controlsClicking direction buttons sends ClientMessage::Move through the WebSocket
Clickable room cardsReachable rooms are highlighted and fire onmove when clicked — the server still validates
Keyboard shortcutsArrow keys / WASD / vim keys send moves via the same onmove callback
LazyLockThread-safe lazy initialization of global server state