โ† All Workshops

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

Run it!

You need at least two terminals. The host starts first, then players connect.

Terminal 1: Start the host
cargo run --features relay
Terminal 2: Connect a desktop player
cargo run
๐Ÿงช Testing the hybrid setup

Three-player test

Terminal 1 โ€” Alice (host):

  1. cargo run --features relay โ€” starts the app with the WebSocket relay
  2. Click Start as Host, enter name "Alice"
  3. The terminal prints Alice's EndpointId (long base32 string)
  4. It also prints ๐ŸŒ Relay listening on ws://0.0.0.0:9090/

Terminal 2 โ€” Bob (desktop client):

  1. cargo run โ€” starts the app (no relay, just P2P)
  2. Click Join a Game
  3. Paste Alice's EndpointId and enter "Bob"
  4. Click Connect โ€” Bob's desktop connects to Alice via QUIC
  5. The grid loads โ€” Bob sees Alice in Town Square

Terminal 3 โ€” Charlie (browser):

  1. Open a browser to http://localhost:9090 (if the relay serves the WASM) or run a separate HTTP server on the dist/ directory
  2. Enter "Charlie" and connect to ws://localhost:9090 (the relay address)
  3. Charlie appears in the game โ€” all three players see each other

What to check

  • LAN play works without internet โ€” mDNS discovers the host's endpoint
  • Desktop โ†’ Host โ€” direct QUIC connection, no relay involved
  • Browser โ†’ Host โ€” WebSocket โ†’ relay โ†’ gossip, transparent to the game
  • Game logic runs on host โ€” can_move(), quest validation all in Alice's app
  • Relay is stateless โ€” if Charlie disconnects and reconnects, the game state is still there on Alice's machine
๐Ÿšฆ Troubleshooting

"Failed to bind endpoint" โ†’ Make sure no other instance is running. iroh binds to a random available port, but the SecretKey must be unique per instance. If you see this error, restart the app.

mDNS discovery doesn't find the host โ†’ Check that both machines are on the same subnet. Some corporate networks block mDNS multicast (port 5353). Fall back to pasting the EndpointId manually.

"Relay mode disabled" when connecting over internet โ†’ Change RelayMode::Disabled to RelayMode::Default in start_host() and connect_to_host(). Iroh will use its global relay network for NAT hole-punching.

WebSocket connection refused โ†’ Make sure the host started with --features relay. The relay binds to port 9090. Check firewall rules.

Two desktop players on the same machine โ†’ Each iroh endpoint needs a unique SecretKey. The code generates one on every launch, so this should work, but you may need to specify different ports if there is a conflict.

WASM build fails โ†’ The browser entry point (main_web.rs) uses use_websocket from dioxus-fullstack. If you removed it from Cargo.toml, add it back behind a web feature flag:

โš ๏ธ WASM limitations

The WASM bundle communicates only through the WebSocket relay. It cannot use iroh or QUIC directly. This means:

  • Browser players depend on the relay being online
  • Browser players cannot host the game (only desktop can)
  • The relay's address must be reachable from the browser (localhost for same-machine testing, or a LAN IP for other devices)