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
- Overview
- Architecture
- Core Components
- Agent API
- Usage Examples
- Error Handling
- Security Features
- Advanced Features
- Configuration
- 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:
- Basic Login (Synchronous)
- Async Login (CompletableFuture)
- Login with OTP
- Login with Callbacks
- Auto-Reconnection Demo
- Error Handling Demo
- Show Game State
- 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.