lighty_launch/
launch.rs

1use lighty_core::time_it;
2use lighty_java::jre_downloader::jre_download;
3use lighty_java::JavaDistribution;
4use lighty_version::version_metadata::VersionBuilder;
5use crate::errors::{InstallerError, InstallerResult};
6use crate::installer::Installer;
7use lighty_loaders::version::Loader;
8use std::sync::Arc;
9use lighty_version::version_metadata::VersionMetaData;
10use tokio::sync::oneshot;
11use lighty_java::jre_downloader::find_java_binary;
12use lighty_java::runtime::JavaRuntime;
13use lighty_loaders::version::Version;
14use crate::arguments::Arguments;
15use tracing::{info, error, debug};
16
17pub trait Launch<'a> {
18    async fn launch(&mut self, username: &str, uuid: &str, java_distribution: JavaDistribution) -> InstallerResult<()>;
19}
20
21impl<'a> Launch<'a> for Version<'a> {
22    async fn launch(&mut self, username: &str, uuid: &str, java_distribution: JavaDistribution) -> InstallerResult<()> {
23
24        let metadata: Arc<VersionMetaData> = match self.loader {
25            Loader::Vanilla => self.get_complete().await.map_err(|_| InstallerError::UnsupportedLoader("Vanilla".into()))?,
26            Loader::Fabric => self.get_fabric_complete().await.map_err(|_| InstallerError::UnsupportedLoader("Fabric".into()))?,
27            Loader::Quilt => self.get_quilt_complete().await.map_err(|_| InstallerError::UnsupportedLoader("Quilt".into()))?,
28            Loader::NeoForge => self.get_neoforge_complete().await.map_err(|_| InstallerError::UnsupportedLoader("NeoForge".into()))?,
29            Loader::LightyUpdater => self.get_lighty_updater_complete().await.map_err(|_| InstallerError::UnsupportedLoader("LightyUpdater".into()))?,
30            _ => return Err(InstallerError::UnsupportedLoader("Unknown".into())),
31        };
32
33        let builder: &VersionBuilder = match metadata.as_ref() {
34            VersionMetaData::VersionBuilder(b) => b,
35            _ => return Err(InstallerError::InvalidMetadata),
36        };
37
38        // Vérifier/installer Java AVANT l'installation de Minecraft
39        let java_version = &builder.java_version.major_version;
40        let java_path = match find_java_binary(&self.java_dirs, &java_distribution, java_version).await {
41            Ok(path) => {
42                info!("[Java] Java {} already installed at: {:?}", java_version, path);
43                path
44            }
45            Err(_) => {
46                // Java non trouvé, on l'installe
47                info!("[Java] Java {} not found, downloading...", java_version);
48
49                jre_download(
50                    &self.java_dirs,
51                    &java_distribution,
52                    java_version,
53                    |current, total| {
54                        debug!("Téléchargement JRE : {}/{}", current, total);
55                    }
56                ).await.map_err(|e| InstallerError::DownloadFailed(format!("JRE download failed: {}", e)))?
57            }
58        };
59
60        info!("[Java] Using Java binary: {:?}", java_path);
61
62        // Installer les dépendances Minecraft APRES le JRE
63        time_it!("Install delay",self.install(builder).await?);
64
65        // Construire les arguments
66        let arguments = self.build_arguments(builder, username, uuid);
67
68        println!("LES ARGUMENTS COMPLET{:?}", arguments);
69
70        // Créer JavaRuntime avec le chemin vers java.exe
71        let java_runtime = JavaRuntime::new(java_path);
72
73        match java_runtime.execute(arguments, &self.game_dirs).await {
74            Ok(mut child) => {
75                let (_tx, rx) = oneshot::channel::<()>();
76
77                // Affiche les logs Java en temps réel dans le terminal
78                fn print_output(_: &(), buf: &[u8]) -> lighty_java::JavaRuntimeResult<()> {
79                    print!("{}", String::from_utf8_lossy(buf));
80                    Ok(())
81                }
82
83                if let Err(e) = java_runtime
84                    .handle_io(&mut child, print_output, print_output, rx, &())
85                    .await
86                {
87                    error!("Erreur IO: {}", e);
88                }
89
90                if let Some(pid) = child.id() {
91                    info!("Processus lancé avec succès, PID: {}", pid);
92                } else {
93                    info!("Processus lancé avec succès, PID non disponible");
94                }
95
96                // tx.send(()); // <- à utiliser si tu veux forcer l'arrêt du process plus tard
97            }
98            Err(e) => {
99                error!("Erreur lors du lancement: {}", e);
100                return Err(InstallerError::DownloadFailed(format!("Launch failed: {}", e)));
101            }
102        }
103
104        Ok(())
105    }
106}