The MMO Project server owns the full session lifecycle for every connected client. Login creates a row in theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/TaylorZaneKirk/MMO-Project/llms.txt
Use this file to discover all available pages before exploring further.
sessions table and returns a session_id. If the connection drops unexpectedly, disconnected_at is stamped on the row and the character’s live map_presence is preserved for a short grace window, allowing the client to reconnect transparently. An explicit logout immediately revokes the session and removes the presence row. Any reconnect attempt after explicit logout is rejected without restoring game state.
Session states
| State | Trigger |
|---|---|
| Created | LoginService creates the sessions row after successful credential verification |
| Active | SessionHandshakeCoordinator completes character load and world entry |
| Disconnected | WebSocket closes unexpectedly; disconnected_at is stamped on the session |
| Reconnected | ReconnectService restores the session within the grace window |
| Expired | expires_at passes without a successful reconnect |
| Revoked | LogoutService sets revoked_at; no further reconnects are accepted |
Login flow
LoginService handles the initial credential exchange. On every login request it first validates that the client’s ProtocolVersion matches the configured PrototypeOptions.ProtocolVersion. Mismatched versions are rejected immediately with login_status: unsupported_version before any database work begins.
Once the version is confirmed, the account is looked up by name. Inactive accounts return account_inactive. Password verification runs through ASP.NET Identity’s PasswordVerificationResult interface — if the result is SuccessRehashNeeded, the hash is transparently upgraded in the database before continuing.
A successful login creates a new sessions row with an expires_at derived from SessionIdleTimeoutMinutes and returns the session_id and account_id to the transport layer.
LoginService returns ok, SessionHandshakeCoordinator drives the account-character load, calls EnterWorldService, and then calls WorldSnapshotService to deliver the initial game state.
LoginService verifies credentials
Checks protocol version, account existence, account active status, and password hash. Creates the
sessions row on success.Reconnect
ReconnectService enforces a 10-second grace window. When a WebSocket closes unexpectedly the session’s disconnected_at timestamp is recorded but the map_presence row is left intact. A reconnect request within that window passes the following checks in order:
- The
session_idmust match a known session (session_invalidotherwise). revoked_atmust be null — explicitly logged-out sessions are rejected immediately.expires_atmust still be in the future (reauthentication_requiredotherwise).disconnected_atmust be set and within 10 seconds ofUtcNow(reauthentication_requiredotherwise).- A
map_presencerow must exist for the character (session_invalidotherwise).
ReconnectService calls SessionRepository.RestoreSessionAsync and returns reconnect_status: restored along with the character’s map_id, tile_x, and tile_y read from the preserved presence row and a hard-coded facing: south.
The reconnect grace window is a hard-coded 10-second constant in
ReconnectService. SessionIdleTimeoutMinutes controls only how long an idle session’s expires_at is extended — not the reconnect window itself.Logout
LogoutService performs an explicit, immediate revocation. It loads the active session and throws if the session is missing or already revoked — double-logout is a programming error, not a silent no-op. If a map_presence row exists for the character, LogoutService calls ICharacterWorldStatePersistencePolicy.PersistFinalStateAsync with CharacterStatePersistenceReason.LoggedOut before removing the row, ensuring the last known position is committed to the characters table.
After persistence, SessionRepository.RevokeSessionAsync stamps revoked_at and MapPresenceRepository.DeletePresenceAsync removes the live row. Any subsequent reconnect attempt against a revoked session returns reconnect_status: session_invalid.
Character state commit
CharacterStateCommitService is the single seam for all character-state persistence. It implements ICharacterWorldStatePersistencePolicy and delegates to CharacterWorldStateSaveService for every write — whether that write originates from a movement step, an explicit logout, a disconnect, or a server shutdown.
CharacterStateCommitService rather than hunting through every service that can alter world state. CharacterStatePersistenceReason gives each caller a clear label (MovementNormalization, LoggedOut, Disconnected, ServerShutdown, Faulted) that can be used for auditing or write-path differentiation.
Persistence tables
| Table | What it stores |
|---|---|
sessions | Login timestamp, disconnected_at, expires_at, revoked_at; one row per authentication attempt |
map_presence | Live map_id, tile_x, tile_y for each connected character; used for session visibility and reconnect restoration |
characters.map_id / tile_x / tile_y | Durable committed position; written immediately by CharacterStateCommitService on every resolved movement step and on logout/disconnect |