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

610 lines
18 KiB
Markdown

# 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<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.
```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<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
```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<AgentAPI.LoginResult> 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.