# OpenOSRS Login System Documentation This document provides comprehensive documentation for the OpenOSRS modernized client login system, designed specifically for AI agent automation. ## Table of Contents 1. [Overview](#overview) 2. [Architecture](#architecture) 3. [Core Components](#core-components) 4. [Agent API](#agent-api) 5. [Usage Examples](#usage-examples) 6. [Error Handling](#error-handling) 7. [Security Features](#security-features) 8. [Advanced Features](#advanced-features) 9. [Configuration](#configuration) 10. [Troubleshooting](#troubleshooting) ## Overview The OpenOSRS login system provides a complete, agent-friendly authentication solution for Old School RuneScape. It offers both synchronous and asynchronous login methods, comprehensive error handling, OTP support, automatic reconnection, and extensive event monitoring. ### Key Features - **Agent-Optimized**: Designed specifically for AI agents with programmatic interfaces - **Comprehensive Authentication**: Support for username/password and OTP authentication - **Asynchronous Operations**: Non-blocking login operations with CompletableFuture support - **Event-Driven**: Complete event system for monitoring login state changes - **Auto-Reconnection**: Automatic reconnection with configurable retry logic - **Error Handling**: Detailed error codes and messages for all failure scenarios - **Session Management**: Proper session token and ID handling - **Security**: Encrypted packet transmission and secure credential handling ## Architecture The login system follows a layered architecture: ``` ┌─────────────────────────────────────────┐ │ Agent API │ ← High-level agent interface ├─────────────────────────────────────────┤ │ Login Screen │ ← UI abstraction layer ├─────────────────────────────────────────┤ │ Login State │ ← State management ├─────────────────────────────────────────┤ │ Event System │ ← Event handling ├─────────────────────────────────────────┤ │ Network Protocol │ ← Network communication ├─────────────────────────────────────────┤ │ Client Core │ ← Core client systems └─────────────────────────────────────────┘ ``` ## Core Components ### LoginState **Location**: `com.openosrs.client.core.CoreStates.LoginState` Manages the current login state and credentials. ```java // State enumeration public enum State { LOGGED_OUT, // Not logged in LOGGING_IN, // Login in progress LOGGED_IN, // Successfully logged in LOGIN_FAILED, // Login failed LOGGED_OUT_TIMEOUT // Logged out due to timeout } // Key methods public void setCredentials(String username, String password, String otp) public void attemptLogin() public void logout() public State getState() public boolean isValidCredentials() ``` ### LoginScreen **Location**: `com.openosrs.client.core.LoginScreen` Provides high-level login screen management for agents. ```java // Synchronous login methods public LoginResult login(String username, String password) public LoginResult login(String username, String password, String otp) public LoginResult loginWithTimeout(String username, String password, int timeoutSeconds) // Asynchronous login methods public CompletableFuture loginAsync(String username, String password) public void loginAsync(String username, String password, Consumer callback) // State queries public boolean isLoggedIn() public boolean isLoginInProgress() public LoginState.State getCurrentState() ``` ### LoginHandler **Location**: `com.openosrs.client.engine.NetworkProtocol.LoginHandler` Handles the network protocol for login authentication. ```java // Core functionality public void handleLoginResponse(NetworkEngine.IncomingMessage message) public void sendLoginRequest(NetworkEngine.OutgoingMessage message) public boolean isLoginInProgress() // Supported login response codes LOGIN_SUCCESS = 0 LOGIN_INVALID_CREDENTIALS = 3 LOGIN_ACCOUNT_DISABLED = 4 LOGIN_ALREADY_ONLINE = 5 LOGIN_WORLD_FULL = 7 // ... and 17 more error codes ``` ### EventSystem **Location**: `com.openosrs.client.core.EventSystem` Provides comprehensive event handling for login operations. ```java // Login-specific event types LOGIN_ATTEMPT_STARTED LOGIN_SUCCESS LOGIN_FAILED LOGIN_PROGRESS LOGOUT DISCONNECTED RECONNECTING // Event listener management public void addListener(EventType type, Consumer listener) public void removeListener(EventType type, Consumer listener) public void fireEvent(EventType type, Event event) ``` ## Agent API **Location**: `com.openosrs.client.api.AgentAPI` The primary interface for AI agents to interact with the login system. ### Basic Login Methods ```java AgentAPI api = new AgentAPI(clientCore); api.initialize(); // Synchronous login (blocking) AgentAPI.LoginResult result = api.login("username", "password"); if (result.isSuccess()) { System.out.println("Login successful! Session: " + result.getSessionId()); } else { System.out.println("Login failed: " + result.getMessage()); } // Asynchronous login (non-blocking) CompletableFuture future = api.loginAsync("username", "password"); future.thenAccept(result -> { if (result.isSuccess()) { System.out.println("Async login successful!"); } }); ``` ### OTP Support ```java // Login with One-Time Password AgentAPI.LoginResult result = api.login("username", "password", "123456"); ``` ### Callback-Based Login ```java // Set up login callbacks api.setLoginCallbacks( result -> System.out.println("Success: " + result), error -> System.out.println("Error: " + error), progress -> System.out.println("Progress: " + progress) ); // Start async login api.loginAsync("username", "password", "otp"); ``` ### Auto-Reconnection ```java // Enable auto-reconnection api.setAutoReconnect(true, 30, 5); // 30 second delay, 5 max attempts // Auto-reconnection will now handle disconnections automatically ``` ### State Monitoring ```java // Check login state boolean loggedIn = api.isLoggedIn(); boolean loginInProgress = api.isLoginInProgress(); LoginState.State state = api.getLoginState(); // Get game state (when logged in) AgentAPI.Position position = api.getPlayerPosition(); int health = api.getPlayerHealth(); boolean moving = api.isPlayerMoving(); ``` ### Event Listening ```java // Listen for login events api.addEventListener(EventSystem.EventType.LOGIN_SUCCESS, event -> { System.out.println("Login successful!"); }); api.addEventListener(EventSystem.EventType.LOGIN_FAILED, event -> { System.out.println("Login failed!"); }); api.addEventListener(EventSystem.EventType.DISCONNECTED, event -> { System.out.println("Connection lost!"); }); ``` ## Usage Examples ### Simple Login Example ```java public class SimpleAgent { public static void main(String[] args) { ClientCore clientCore = new ClientCore(); AgentAPI api = new AgentAPI(clientCore); try { clientCore.initialize(); api.initialize(); AgentAPI.LoginResult result = api.login("myusername", "mypassword"); if (result.isSuccess()) { System.out.println("Successfully logged in!"); // Agent is now ready to play while (api.isLoggedIn()) { // Game logic here Thread.sleep(1000); } } else { System.out.println("Login failed: " + result.getMessage()); } } catch (Exception e) { e.printStackTrace(); } finally { api.shutdown(); clientCore.shutdown(); } } } ``` ### Advanced Agent with Auto-Reconnection ```java public class AdvancedAgent { private ClientCore clientCore; private AgentAPI api; private volatile boolean running = true; public void start() { clientCore = new ClientCore(); api = new AgentAPI(clientCore); try { clientCore.initialize(); api.initialize(); // Enable auto-reconnection api.setAutoReconnect(true, 30, 10); // Set up event monitoring setupEventListeners(); // Initial login performLogin(); // Main game loop gameLoop(); } catch (Exception e) { e.printStackTrace(); } finally { cleanup(); } } private void setupEventListeners() { api.addEventListener(EventSystem.EventType.LOGIN_SUCCESS, event -> { System.out.println("✅ Connected and ready!"); }); api.addEventListener(EventSystem.EventType.DISCONNECTED, event -> { System.out.println("🔌 Connection lost - auto-reconnection will handle this"); }); api.addEventListener(EventSystem.EventType.LOGIN_FAILED, event -> { System.out.println("❌ Login failed - check credentials"); }); } private void performLogin() { String username = System.getenv("OSRS_USERNAME"); String password = System.getenv("OSRS_PASSWORD"); String otp = System.getenv("OSRS_OTP"); if (username == null || password == null) { throw new IllegalArgumentException("Username and password must be set in environment variables"); } api.loginAsync(username, password, otp).thenAccept(result -> { if (!result.isSuccess()) { System.err.println("Initial login failed: " + result.getMessage()); running = false; } }); } private void gameLoop() { while (running) { try { if (api.isLoggedIn()) { // Perform game actions doGameAction(); } else { // Wait for reconnection Thread.sleep(1000); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } } } private void doGameAction() { // Example game logic AgentAPI.Position pos = api.getPlayerPosition(); int health = api.getPlayerHealth(); System.out.println("Player at " + pos + ", health: " + health); try { Thread.sleep(5000); // Wait 5 seconds between actions } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } private void cleanup() { if (api != null) { api.logout(); api.shutdown(); } if (clientCore != null) { clientCore.shutdown(); } } } ``` ## Error Handling The login system provides comprehensive error handling with specific error codes and messages. ### Login Error Codes | Code | Constant | Description | |------|----------|-------------| | 0 | LOGIN_SUCCESS | Login successful | | 3 | LOGIN_INVALID_CREDENTIALS | Invalid username or password | | 4 | LOGIN_ACCOUNT_DISABLED | Account has been disabled | | 5 | LOGIN_ALREADY_ONLINE | Account is already logged in | | 6 | LOGIN_SERVER_UPDATED | Game updated - reload client | | 7 | LOGIN_WORLD_FULL | World is full | | 8 | LOGIN_LOGIN_SERVER_OFFLINE | Login server offline | | 9 | LOGIN_LOGIN_LIMIT_EXCEEDED | Too many connections | | 10 | LOGIN_BAD_SESSION_ID | Unable to connect | | 11 | LOGIN_FORCE_PASSWORD_CHANGE | Password change required | | 12 | LOGIN_NEED_MEMBERS_ACCOUNT | Members account required | | 13 | LOGIN_COULD_NOT_COMPLETE_LOGIN | Could not complete login | | 14 | LOGIN_SERVER_BEING_UPDATED | Server being updated | | 15 | LOGIN_RECONNECTING | Reconnecting | | 16 | LOGIN_LOGIN_ATTEMPTS_EXCEEDED | Too many login attempts | | 17 | LOGIN_MEMBERS_ONLY_AREA | Members only area | | 18 | LOGIN_LOCKED_ACCOUNT | Account locked | | 19 | LOGIN_CLOSE_OTHER_CONNECTION | Close other connection | | 20 | LOGIN_MALFORMED_PACKET | Malformed packet | | 21 | LOGIN_NO_REPLY_FROM_LOGIN_SERVER | No reply from login server | | 22 | LOGIN_ERROR_LOADING_PROFILE | Error loading profile | | 23 | LOGIN_UNKNOWN_REPLY_FROM_LOGIN_SERVER | Unknown reply from login server | | 26 | LOGIN_IP_BLOCKED | IP address blocked | ### Error Handling Examples ```java AgentAPI.LoginResult result = api.login("username", "password"); if (!result.isSuccess()) { String message = result.getMessage(); if (message.contains("Invalid username or password")) { // Handle credential error System.out.println("Credentials are incorrect"); } else if (message.contains("World is full")) { // Try different world System.out.println("World is full, trying different world"); } else if (message.contains("too many login attempts")) { // Wait before retrying System.out.println("Rate limited, waiting before retry"); Thread.sleep(60000); // Wait 1 minute } } ``` ## Security Features ### Credential Security - Credentials are not stored in plain text - Passwords are cleared from memory after use - OTP codes are handled securely - Session tokens are encrypted in transmission ### Network Security - All login packets are encrypted - Session verification prevents replay attacks - Automatic session timeout handling - Secure random session ID generation ### Best Practices ```java // Store credentials securely String username = System.getenv("OSRS_USERNAME"); String password = System.getenv("OSRS_PASSWORD"); String otp = System.getenv("OSRS_OTP"); // Use environment variables, not hardcoded strings AgentAPI.LoginResult result = api.login(username, password, otp); // Clear sensitive data username = null; password = null; otp = null; ``` ## Advanced Features ### Session Management ```java // Get session information if (api.isLoggedIn()) { LoginState loginState = clientCore.getLoginState(); int sessionId = loginState.getSessionId(); String sessionToken = loginState.getSessionToken(); System.out.println("Session ID: " + sessionId); System.out.println("Session Token: " + sessionToken); } ``` ### Timeout Configuration ```java // Custom login timeout AgentAPI.LoginResult result = api.login("username", "password", null, 60); // 60 second timeout ``` ### Progress Monitoring ```java api.setLoginCallbacks( null, // success callback null, // error callback progress -> System.out.println("Login progress: " + progress) // progress callback ); ``` ## Configuration ### Environment Variables ```bash # Required for login export OSRS_USERNAME="your_username" export OSRS_PASSWORD="your_password" # Optional export OSRS_OTP="123456" # If using OTP export OSRS_WORLD="301" # Preferred world export OSRS_AUTO_RECONNECT="true" # Enable auto-reconnection ``` ### System Properties ```bash # Enable debug logging -Dorg.slf4j.simpleLogger.defaultLogLevel=DEBUG # Custom timeouts -Dosrs.login.timeout=30000 -Dosrs.reconnect.delay=30000 -Dosrs.reconnect.maxAttempts=5 ``` ## Troubleshooting ### Common Issues **Login Timeout** ``` Error: Login timeout or error: TimeoutException ``` *Solution*: Increase timeout or check network connectivity **Invalid Credentials** ``` Error: Invalid username or password ``` *Solution*: Verify credentials, check for typos **World Full** ``` Error: This world is full. Please use a different world ``` *Solution*: Try different world or wait for space **Too Many Attempts** ``` Error: Too many login attempts. Please wait a few minutes ``` *Solution*: Wait before retrying, implement exponential backoff ### Debug Logging Enable debug logging to troubleshoot issues: ```java // In code System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "DEBUG"); // Or via JVM arguments -Dorg.slf4j.simpleLogger.defaultLogLevel=DEBUG -Dorg.slf4j.simpleLogger.showDateTime=true -Dorg.slf4j.simpleLogger.dateTimeFormat=HH:mm:ss.SSS ``` ### Network Issues ```java // Test network connectivity if (!api.isLoggedIn()) { // Check if it's a network issue try { InetAddress.getByName("oldschool.runescape.com").isReachable(5000); System.out.println("Network connectivity OK"); } catch (IOException e) { System.out.println("Network connectivity issues: " + e.getMessage()); } } ``` ## Running the Example To run the login example: ```bash # Using Gradle ./gradlew runLoginExample # Or compile and run directly ./gradlew build java -cp build/libs/modernized-client-1.0.0.jar com.openosrs.client.examples.ExampleLoginAgent ``` The example provides an interactive menu to test different login scenarios: 1. Basic Login (Synchronous) 2. Async Login (CompletableFuture) 3. Login with OTP 4. Login with Callbacks 5. Auto-Reconnection Demo 6. Error Handling Demo 7. Show Game State 8. Logout and Exit --- **Note**: This documentation covers the complete login system implementation. All features are designed to work seamlessly with AI agents while providing the flexibility and reliability needed for automated gameplay.