← All Workshops

MudEngine Part 11: Peer-to-Peer (Hybrid)

From Fullstack to P2P

In Parts 6–10 the MudEngine relied on a central Axum server to own the game state, validate moves, and broadcast updates. Every player — whether in a browser or a native window — connected to that same server.

In this part we tear down the server and replace it with direct peer-to-peer connections built on iroh. The architecture is a hybrid that supports both native desktop clients and browser-based players:

The host's desktop app runs the authoritative GameState — the same can_move(), update_quest(), and save_game_state() code from Parts 7–9. Desktop peers connect directly via QUIC. Browser peers connect through a lightweight WebSocket relay that the host runs alongside the game.

No central server. No fullstack. No dx serve for the desktop app.

What changes from Part 10

  • Dioxus Fullstack is removed — no Axum, no server functions, no SSR
  • iroh is added — endpoints, gossip, mDNS discovery
  • Game logic is extracted from the server-only module into a shared library
  • A WebSocket relay is added for browser clients
  • The app runs with cargo rundx is only needed if you also build the WASM bundle for browser players

Prerequisites

  • Complete Parts 1–10 of MudEngine (or at least Part 10 with the Blitz desktop app)
  • A terminal and a text editor
"💻 Host (desktop)" "Clients" "QUIC" "gossip" "WebSocket" Dioxus UI (Blitz) GameState can_move / quest / save iroh Endpoint + gossip WebSocket relay 🎮 Desktop Player iroh QUIC 🌐 Browser Player WebSocket → relay
🔍 How it works
ClientConnectionHow
Host (desktop)Owns the game stateRuns an iroh endpoint + gossip + game logic
Desktop playerDirect P2PDials the host's iroh endpoint via QUIC
Browser playerVia relayWebSocket to a tiny relay that pipes into iroh-gossip