Skip to main content

wormhole_common/finder/
steam.rs

1use std::{fs, path::PathBuf};
2
3use keyvalues_parser::Vdf;
4
5#[cfg(target_os = "linux")]
6use super::resolver::linux;
7#[cfg(target_os = "macos")]
8use super::resolver::macos;
9#[cfg(target_os = "windows")]
10use super::resolver::windows;
11
12#[derive(Default, Clone, Debug)]
13pub struct LibraryFolders {
14    pub paths: Vec<PathBuf>,
15    pub discovered: bool,
16}
17
18impl LibraryFolders {
19    pub fn new() -> Self {
20        return Self {
21            paths: vec![],
22            discovered: false,
23        };
24    }
25
26    #[cfg(target_os = "macos")]
27    pub fn get_library_folders_file(&self) -> PathBuf {
28        return macos::get_steam_library_folders_file();
29    }
30
31    #[cfg(target_os = "linux")]
32    pub fn get_library_folders_file(&self) -> PathBuf {
33        return linux::get_steam_library_folders_file();
34    }
35
36    #[cfg(target_os = "windows")]
37    pub fn get_library_folders_file(&self) -> PathBuf {
38        return windows::get_steam_library_folders_file();
39    }
40
41    pub fn discover(&mut self) -> Option<&mut Self> {
42        let libraryfolders_vdf_path = self.get_library_folders_file();
43
44        if libraryfolders_vdf_path.is_file() {
45            let vdf_text = fs::read_to_string(&libraryfolders_vdf_path).ok()?;
46            let value = Vdf::parse(&vdf_text).ok()?.value;
47            let obj = value.get_obj()?;
48
49            let library_folders: Vec<_> = obj
50                .iter()
51                .filter(|(key, values)| key.parse::<u32>().is_ok() && values.len() == 1)
52                .filter_map(|(_, values)| {
53                    let library_folder_string = values
54                        .get(0)?
55                        .get_obj()?
56                        .get("path")?
57                        .get(0)?
58                        .get_str()?
59                        .to_string();
60
61                    let library_folder = PathBuf::from(library_folder_string).join("steamapps");
62
63                    return Some(library_folder);
64                })
65                .collect();
66
67            self.paths = library_folders;
68        }
69
70        self.discovered = true;
71
72        return Some(self);
73    }
74}
75
76pub struct SteamInstallFinder {
77    pub library_folders: LibraryFolders,
78}
79
80impl Default for SteamInstallFinder {
81    fn default() -> Self {
82        let mut me = Self {
83            library_folders: LibraryFolders::new(),
84        };
85
86        me.library_folders
87            .discover()
88            .expect("Failed to discover Steam library folders!");
89
90        return me;
91    }
92}
93
94impl SteamInstallFinder {
95    pub fn find_ksp2_dir(&mut self) -> Option<PathBuf> {
96        for library_folder in self.library_folders.clone().paths {
97            let ksp2_dir = library_folder.join("common").join("Kerbal Space Program 2");
98
99            if ksp2_dir.is_dir() {
100                let dir_contents = fs::read_dir(&ksp2_dir).unwrap().flatten();
101
102                for file in dir_contents {
103                    let file_path = file.path();
104
105                    if file_path.is_file()
106                        && file_path
107                            .as_os_str()
108                            .to_str()
109                            .unwrap()
110                            .contains("KSP2_x64.exe")
111                    {
112                        return Some(ksp2_dir);
113                    }
114                }
115            }
116        }
117
118        return None;
119    }
120
121    pub fn find_ksp1_dir(&mut self) -> Option<PathBuf> {
122        for library_folder in self.library_folders.clone().paths {
123            let ksp2_dir = library_folder.join("common").join("Kerbal Space Program");
124
125            if ksp2_dir.is_dir() {
126                let dir_contents = fs::read_dir(&ksp2_dir).unwrap().flatten();
127
128                for file in dir_contents {
129                    let file_path = file.path();
130
131                    if file_path.is_file()
132                        && file_path
133                            .as_os_str()
134                            .to_str()
135                            .unwrap()
136                            .contains("KSP_x64.exe")
137                    {
138                        return Some(ksp2_dir);
139                    }
140                }
141            }
142        }
143
144        return None;
145    }
146}