late-java-core 2.2.9

A Rust library for launching Minecraft Java Edition
use late_java_core::{
    Launch, MicrosoftAuth, LaunchOptions, MemoryOptions, LoaderOptions, 
    ScreenOptions, JavaOptions, VersionManifest, StatusClient, init_logger
};
use std::collections::HashMap;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    init_logger();

    println!("=== Late Java Core - Ejemplo Completo ===");
    
    // 1. Mostrar versiones disponibles
    println!("\n1. Obteniendo versiones disponibles...");
    let manifest = VersionManifest::fetch().await?;
    println!("   Última release: {}", manifest.latest.release);
    println!("   Última snapshot: {}", manifest.latest.snapshot);
    
    // Mostrar algunas versiones
    println!("   Versiones disponibles:");
    for (i, version) in manifest.versions.iter().take(5).enumerate() {
        println!("     {}. {} ({})", i + 1, version.id, version.r#type);
    }

    // 2. Autenticación Microsoft
    println!("\n2. Autenticación Microsoft...");
    let auth = MicrosoftAuth::new("00000000402b5328".to_string());
    
    // En un ejemplo real, descomenta la siguiente línea:
    // let auth_result = auth.authenticate().await?;
    // println!("   Autenticado como: {}", auth_result.name);
    
    // Para el ejemplo, creamos un resultado simulado
    let auth_result = late_java_core::AuthResponse {
        access_token: "simulated_token".to_string(),
        client_token: "simulated_client_token".to_string(),
        uuid: "simulated_uuid".to_string(),
        name: "TestUser".to_string(),
        refresh_token: Some("simulated_refresh_token".to_string()),
        user_properties: "{}".to_string(),
        meta: late_java_core::auth::AuthMeta {
            auth_type: "Xbox".to_string(),
            access_token_expires_in: chrono::Utc::now().timestamp() as u64 + 3600,
            demo: false,
        },
        xbox_account: Some(late_java_core::auth::XboxAccount {
            xuid: "simulated_xuid".to_string(),
            gamertag: "TestGamer".to_string(),
            age_group: "Adult".to_string(),
        }),
        profile: None,
    };

    // 3. Ping a servidor (ejemplo)
    println!("\n3. Ping a servidor...");
    match StatusClient::ping("mc.hypixel.net", 25565) {
        Ok(result) => {
            println!("   Servidor: {}", result.server_info.description.text);
            println!("   Jugadores: {}/{}", result.server_info.players.online, result.server_info.players.max);
            println!("   Latencia: {}ms", result.latency);
        }
        Err(e) => {
            println!("   Error al hacer ping: {}", e);
        }
    }

    // 4. Configuración avanzada del launcher
    println!("\n4. Configurando launcher...");
    
    let mut custom_headers = HashMap::new();
    custom_headers.insert("User-Agent".to_string(), "LateJavaCore/2.2.9".to_string());
    
    let options = LaunchOptions {
        // Configuración básica
        path: "./minecraft".to_string(),
        version: "1.20.4".to_string(),
        authenticator: auth_result,
        
        // Configuración de red
        url: Some("https://launchermeta.mojang.com".to_string()),
        headers: Some(custom_headers),
        timeout: Some(30000),
        
        // Configuración de instancia
        instance: Some("modded".to_string()),
        detached: Some(false),
        download_file_multiple: Some(10),
        bypass_offline: Some(false),
        
        // Configuración de memoria
        memory: MemoryOptions {
            min: "4G".to_string(),
            max: "8G".to_string(),
        },
        
        // Configuración de pantalla
        screen: ScreenOptions {
            width: Some(1920),
            height: Some(1080),
            fullscreen: false,
        },
        
        // Configuración de Java
        java: JavaOptions {
            path: None, // Usar Java del sistema
            version: Some("17".to_string()),
            java_type: "jre".to_string(),
        },
        
        // Configuración del loader
        loader: LoaderOptions {
            path: Some("./loader".to_string()),
            loader_type: Some("fabric".to_string()),
            build: Some("0.15.9".to_string()),
            enable: true,
        },
        
        // Configuración MCP (opcional)
        mcp: None,
        
        // Verificación de archivos
        verify: Some(true),
        ignored: vec!["saves".to_string(), "screenshots".to_string()],
        
        // Argumentos personalizados
        jvm_args: vec![
            "-XX:+UseG1GC".to_string(),
            "-XX:+ParallelRefProcEnabled".to_string(),
            "-XX:MaxGCPauseMillis=200".to_string(),
            "-XX:+UnlockExperimentalVMOptions".to_string(),
            "-XX:G1NewSizePercent=20".to_string(),
            "-XX:G1ReservePercent=20".to_string(),
            "-XX:G1HeapRegionSize=32M".to_string(),
        ],
        game_args: vec![
            "--quickPlaySingleplayer".to_string(),
            "test_world".to_string(),
        ],
    };
    
    println!("   Configuración completada:");
    println!("     - Ruta: {}", options.path);
    println!("     - Versión: {}", options.version);
    println!("     - Instancia: {:?}", options.instance);
    println!("     - Memoria: {} - {}", options.memory.min, options.memory.max);
    println!("     - Pantalla: {:?}x{:?}", options.screen.width, options.screen.height);
    println!("     - Java: {:?}", options.java.version);
    println!("     - Loader: {:?} {:?}", options.loader.loader_type, options.loader.build);
    println!("     - Descargas concurrentes: {:?}", options.download_file_multiple);
    println!("     - Argumentos JVM: {} argumentos", options.jvm_args.len());
    println!("     - Argumentos del juego: {} argumentos", options.game_args.len());

    // 5. Crear launcher y suscribirse a eventos
    println!("\n5. Creando launcher...");
    let mut launcher = Launch::new();
    let mut event_receiver = launcher.subscribe();
    
    // Escuchar eventos en un hilo separado
    let event_handle = tokio::spawn(async move {
        while let Ok(event) = event_receiver.recv().await {
            match event {
                late_java_core::LaunchEvent::Progress { downloaded, total, element } => {
                    let percentage = if total > 0 { (downloaded * 100) / total } else { 0 };
                    println!("   Progreso: {}% ({}/{} bytes) - {:?}", percentage, downloaded, total, element);
                }
                late_java_core::LaunchEvent::Speed(speed) => {
                    println!("   Velocidad: {:.2} KB/s", speed / 1024.0);
                }
                late_java_core::LaunchEvent::Estimated(time) => {
                    println!("   Tiempo restante: {:.0} segundos", time);
                }
                late_java_core::LaunchEvent::Extract(file) => {
                    println!("   Extrayendo: {}", file);
                }
                late_java_core::LaunchEvent::Data(data) => {
                    println!("   Minecraft: {}", data.trim());
                }
                late_java_core::LaunchEvent::Close(msg) => {
                    println!("   {}", msg);
                    break;
                }
                late_java_core::LaunchEvent::Error(err) => {
                    println!("   Error: {}", err);
                    break;
                }
                _ => {}
            }
        }
    });

    // 6. Lanzar Minecraft
    println!("\n6. Lanzando Minecraft...");
    println!("   (En un ejemplo real, esto lanzaría Minecraft)");
    
    // En un ejemplo real, descomenta la siguiente línea:
    // launcher.launch(options).await?;
    
    // Simular el lanzamiento
    tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
    println!("   Minecraft lanzado exitosamente!");
    
    // Esperar a que termine el evento handler
    event_handle.abort();

    // 7. Mostrar información adicional
    println!("\n7. Información adicional:");
    println!("   - Versión de la librería: {}", late_java_core::VERSION);
    println!("   - Plataforma: {} {}", std::env::consts::OS, std::env::consts::ARCH);
    println!("   - Rust: {}", env!("RUSTC_SEMVER"));
    
    println!("\n=== Ejemplo completado ===");
    Ok(())
}