Files
aiscape/modernized-client/docs/LOGIN_SYSTEM.md
2025-09-06 08:33:20 -07:00

18 KiB

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
  2. Architecture
  3. Core Components
  4. Agent API
  5. Usage Examples
  6. Error Handling
  7. Security Features
  8. Advanced Features
  9. Configuration
  10. 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.

// 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.

// 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<LoginResult> loginAsync(String username, String password)
public void loginAsync(String username, String password, Consumer<LoginResult> 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.

// 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.

// 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<Event> listener)
public void removeListener(EventType type, Consumer<Event> 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

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<AgentAPI.LoginResult> future = api.loginAsync("username", "password");
future.thenAccept(result -> {
    if (result.isSuccess()) {
        System.out.println("Async login successful!");
    }
});

OTP Support

// Login with One-Time Password
AgentAPI.LoginResult result = api.login("username", "password", "123456");

Callback-Based Login

// 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

// Enable auto-reconnection
api.setAutoReconnect(true, 30, 5); // 30 second delay, 5 max attempts

// Auto-reconnection will now handle disconnections automatically

State Monitoring

// 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

// 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

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

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

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

// 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

// 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

// Custom login timeout
AgentAPI.LoginResult result = api.login("username", "password", null, 60); // 60 second timeout

Progress Monitoring

api.setLoginCallbacks(
    null, // success callback
    null, // error callback
    progress -> System.out.println("Login progress: " + progress) // progress callback
);

Configuration

Environment Variables

# 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

# 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:

// 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

// 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:

# 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.