← All Workshops

MudEngine Part 6: Multiplayer

Step 12 / 12
◀ Prev

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 via Input component), move (D-pad via Button component), leave (disconnect detection)
  • Part 5 components reusedRoomCell shows occupant names per grid cell, Card wraps the description, Button drives the D-pad, Input handles name registration

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
RoomCell (custom)Reusable grid cell with name, active, and players props — shows occupant names per room
Button / ButtonVariantClickable direction buttons from dioxus-components sending ClientMessage::Move through the WebSocket
Card / CardHeader / CardTitle / CardContentStructured description panel with theme styling from dioxus-components
InputThemed name input from dioxus-components for player registration
SeparatorHorizontal divider in the description card
mod components;Declaring the dioxus-components module auto-generated in Part 5
LazyLockThread-safe lazy initialization of global server state
Step 12 / 12
◀ Prev