mud/docs/how/persistence.txt

92 lines
2.8 KiB
Text

PERSISTENCE
This document explains how player accounts and state are persisted to disk.
WHAT'S PERSISTED
Player accounts:
- Username (case-insensitive)
- Password (hashed with PBKDF2-HMAC-SHA256 and random salt)
- Position (zone, x, y — see object-model.rst for location system)
- Combat stats (pl, stamina, max_stamina)
- Flying status
- Created timestamp
- Last login timestamp
What's NOT persisted (runtime state only):
- Telnet I/O (writer, reader)
- Mode stack (normal/combat/editor modes)
- Active effects
- Combat encounters
- Commands being executed
DATABASE LOCATION
Default: data/mud.db (SQLite)
The database is initialized on server startup via init_db(). The store module
uses a simple module-level _db_path variable to track the connection.
LOGIN FLOW
New player:
1. Enter name
2. If account doesn't exist, prompt "Create new account? (y/n)"
3. If yes, prompt for password twice (must match)
4. Create account with hashed password
5. Start at default position (world center, or nearest passable tile)
Existing player:
1. Enter name
2. Prompt for password
3. Verify password (max 3 attempts)
4. Load saved position and stats
5. If saved position is no longer passable (world changed), find nearest
passable tile
WHEN SAVES HAPPEN
1. On quit: When player types "quit" command
2. On disconnect: When connection is lost (network error, timeout, etc)
3. Periodic auto-save: Every 60 seconds for all connected players
The periodic auto-save runs in the game loop alongside combat and effects
processing. It only triggers if at least one player is connected.
WHAT'S NOT YET PERSISTED
The object model (object-model.rst) introduces containment, inventory, and
zones. Persistence for these is an open question:
- Player inventory (Things with location=player)
- Item instances on the ground (Things with location=zone)
- Container state (open/closed/locked, contents)
- Zone edits from paint mode (tile changes)
- Mob respawn state
These will be addressed as each system gets implemented. Player inventory
will likely go in SQLite alongside account data. Zone edits will persist to
TOML files. Mob instances probably don't persist (respawn from templates).
IMPLEMENTATION NOTES
Password hashing:
- Uses hashlib.pbkdf2_hmac (stdlib, no external dependencies)
- 100,000 iterations of SHA-256
- Random 32-byte salt per account (from os.urandom)
- Both hash and salt stored in database
Case-insensitive names:
- SQLite COLLATE NOCASE on name column
- "Jared", "jared", and "JARED" are the same account
Synchronous operations:
- Store module uses sync sqlite3 (not async)
- Save operations are fast enough for our scale
- Game loop calls save_player() directly (doesn't block tick processing)
TESTING
See tests/test_store.py for store module unit tests
See tests/test_login_flow.py for login/registration integration tests
See tests/test_persistence.py for save-on-quit and auto-save tests