← All Workshops
MudEngine Part 6: Multiplayer
Step 6 / 18
Shared Message Types
Both the client and the server need the same message types. These enums are what we send over the WebSocket connection.
ClientMessage flows from the player to the server:
Move { direction }— the player pressed a movement button
ServerMessage flows from the server to all connected players:
State— initial state sent when a player first joins (full player list + their own ID)PlayerJoined— a new player entered the worldPlayerMoved— a player changed roomsPlayerLeft— a player disconnected
We also define a PlayerInfo struct that holds a player's ID, name, and current room index.
These types are shared — compiled into both the server and the WASM client — so they live in the game module, not in any UI component. Create src/game/messages.rs with them:
mud-engine/src/game/messages.rs
use serde::{Deserialize, Serialize}; // ── Shared message types ── #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct PlayerInfo { pub id: String, pub name: String, pub room: usize, } #[derive(Serialize, Deserialize, Debug, Clone)] pub enum ClientMessage { Move { direction: String }, } #[derive(Serialize, Deserialize, Debug, Clone)] pub enum ServerMessage { State { players: Vec<PlayerInfo>, your_id: String, }, PlayerJoined(PlayerInfo), PlayerMoved(PlayerInfo), PlayerLeft { id: String }, }
🎯 Why derive Clone + PartialEq?
Serialize/Deserialize— messages travel over the WebSocket as JSON; serde handles the encodingClone— messages arrive on the client and need to be stored in signals (likeSignal<HashMap<String, PlayerInfo>>)PartialEq— required by Dioxus props, though our game component doesn't use props directlyDebug— useful for logging and debugging
The message enums are "tagged" — serde encodes the variant name as a string field, making it easy to inspect with browser dev tools.
Step 6 / 18