← All Workshops

MudEngine Part 7: Save & Load

Step 10 / 10
◀ Prev

Congratulations!

You just added persistent game state to the MUD engine!

What we achieved:

  • Data-driven world — the full 9-room grid is defined in game.toml, editable without recompiling
  • Server-side persistence — player positions are saved to disk on every join, move, and leave
  • Client-server synchronisation — room data is sent from the server to the client in the initial State message, eliminating the hardcoded statics
  • Save/load architectureload_game_state() at startup, save_game_state() after every mutation, can_move() for movement validation from loaded data
  • Cleanup — the old ROOM_NAMES, ROOM_DESCS, and EXITS statics are gone; the game is fully data-driven

Architecture recap

game.toml ──read──▶  LazyLock ──▶ GameState { rooms, players }
                           │
              ┌────────────┼────────────┐
              ▼            ▼            ▼
         Player join   Player move   Player leave
              │            │            │
              └────────────┼────────────┘
                           ▼
                    save_game_state()
                           │
                           ▼
                    game.toml (updated)

What's next?

The dungeon keeps growing! Future parts could explore:

  • SQLite database — replace game.toml with sqlx + SQLite for concurrent read/write access
  • Room state — locked doors, dark rooms that need a torch, writable signs
  • Inventory — items the player can pick up, carry between rooms, and drop
  • Chat — add a chat panel where players can send messages to each other
  • Monsters & combat — NPCs roaming the world, attack commands, health bars
  • Editor UI — an admin panel to edit room data from the browser

The MUD persists! 🏰💾

📚 What we learned
ConceptHow we used it
serde + tomlDeserialize game.toml into TomlGame, serialize GameState back
LazyLock<Mutex<T>>Thread-safe, lazily-initialised global game state
load_game_state()Reads TOML, converts to runtime types, panics on missing file
save_game_state()Converts runtime state back to TOML types, writes to disk
RoomInfoShared type sent from server to client in initial State message
Data-driven designWorld definition lives in a data file, not in source code
Persistence on mutationEvery player join/move/leave triggers an immediate disk write
can_move()Movement validation using room-ID-based lookup instead of index-based slices
Step 10 / 10
◀ Prev