Skip to main content

wormhole_common/installer/
bepinex.rs

1use zip::ZipArchive;
2
3use crate::downloader::Downloader;
4use std::{
5    fs::{self, File},
6    path::PathBuf,
7};
8
9pub struct BepInExInstallManager {
10    pub ksp2_install_path: PathBuf,
11    pub zip_url: String,
12}
13
14impl BepInExInstallManager {
15    pub fn new(ksp2_install_path: PathBuf) -> Self {
16        return BepInExInstallManager {
17            ksp2_install_path,
18
19            // For now, this is hard-coded because SpaceWarp uses BepInEx 5,
20            // which is now in LTS mode. I would fetch the latest release
21            // from GitHub, but I don't want to accidentally download
22            // BepInEx 6 instead.
23            zip_url: "https://github.com/BepInEx/BepInEx/releases/download/v5.4.21/BepInEx_x64_5.4.21.0.zip".to_string(),
24        };
25    }
26
27    pub async fn download<W>(
28        &mut self,
29        on_progress: fn(u64, usize, W) -> (),
30        on_finish: fn(u64, W) -> (),
31        window: W,
32    ) -> Result<(), String>
33    where
34        W: Clone,
35    {
36        if !self.ksp2_install_path.is_dir() {
37            return Err("KSP2 install path is not a directory!".to_string());
38        }
39
40        let files_in_dir = self.ksp2_install_path.read_dir().unwrap();
41
42        for file in files_in_dir {
43            let file = file.unwrap();
44            let file_name = file.file_name().into_string().unwrap();
45
46            if file_name.contains("doorstop_config.ini")
47                || file_name.contains(".doorstop_version")
48                || file_name.contains("winhttp.dll")
49                || file_name.contains("version.dll")
50                || file_name.contains("BepInEx")
51            {
52                return Err("BepInEx or another mod loader is already installed!".to_string());
53            }
54        }
55
56        let download_url = self.zip_url.clone();
57
58        println!("Downloading from URL: {}", download_url);
59
60        let out_file = self.ksp2_install_path.join(".bepinex_release.zip");
61
62        Downloader::download(
63            download_url,
64            out_file.clone(),
65            on_progress,
66            on_finish,
67            window,
68        )
69        .await;
70
71        let mut zip = ZipArchive::new(File::open(out_file.clone()).unwrap()).unwrap();
72
73        zip.extract(self.ksp2_install_path.clone())
74            .expect("Could not extract the BepInEx release!");
75
76        fs::remove_file(out_file).expect("Could not delete the BepInEx release file!");
77
78        return Ok(());
79    }
80}