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 (x, y coordinates) - 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. 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