#[allow(deprecated)]
use std::env::home_dir;
use std::fs;
use std::fs::read_dir;
use std::path::PathBuf;
use physis::common::Platform;
use physis::resource::SqPackResource;
#[derive(Clone, Copy)]
#[repr(C)]
pub enum ExistingInstallType {
OfficialLauncher,
XIVQuickLauncher,
XIVLauncherCore,
XIVOnMac,
Astra,
}
pub struct ExistingGameDirectory {
pub install_type: ExistingInstallType,
pub path: String,
pub version: String,
}
fn read_version(path: &str) -> String {
let mut path = PathBuf::from(path);
path.push("game");
let path = path.to_str().unwrap().to_string();
let game_data = SqPackResource::from_existing(Platform::Win32, &path);
if let Some(latest_repository) = game_data.repositories.last() {
return latest_repository.version.clone().unwrap_or_default();
}
String::default()
}
pub fn find_existing_game_dirs() -> Vec<ExistingGameDirectory> {
let mut install_dirs = Vec::new();
match std::env::consts::OS {
"linux" => {
{
let path = from_home_dir(
".steam/steam/steamapps/common/FINAL FANTASY XIV - A Realm Reborn",
);
install_dirs.push(ExistingGameDirectory {
install_type: ExistingInstallType::OfficialLauncher,
path: path.clone(),
version: read_version(&path),
});
}
{
let path = from_home_dir(".xlcore/ffxiv");
install_dirs.push(ExistingGameDirectory {
install_type: ExistingInstallType::XIVLauncherCore,
path: path.clone(),
version: read_version(&path),
});
}
if let Ok(entries) = read_dir(from_home_dir(".local/share/astra/game/")) {
entries
.flatten()
.flat_map(|entry| {
let Ok(meta) = entry.metadata() else {
return vec![];
};
if meta.is_dir() {
return vec![entry.path()];
}
vec![]
})
.for_each(|path| {
let path = path.to_str().unwrap().to_string();
let version = read_version(&path);
install_dirs.push(ExistingGameDirectory {
install_type: ExistingInstallType::Astra,
path,
version,
})
});
}
}
"macos" => {
{
let path = from_home_dir(
"Library/Application Support/FINAL FANTASY XIV ONLINE/Bottles/published_Final_Fantasy/drive_c/Program Files (x86)/SquareEnix/FINAL FANTASY XIV - A Realm Reborn",
);
install_dirs.push(ExistingGameDirectory {
install_type: ExistingInstallType::OfficialLauncher,
path: path.clone(),
version: read_version(&path),
});
}
}
"windows" => {
{
let path =
"C:\\Program Files (x86)\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn"
.to_string();
install_dirs.push(ExistingGameDirectory {
install_type: ExistingInstallType::OfficialLauncher,
path: path.clone(),
version: read_version(&path),
});
}
}
&_ => {}
}
install_dirs
.into_iter()
.filter(|dir| is_valid_game_dir(&dir.path))
.filter(|dir| !dir.version.is_empty())
.collect()
}
pub struct ExistingUserDirectory {
pub install_type: ExistingInstallType,
pub path: String,
}
pub fn find_existing_user_dirs() -> Vec<ExistingUserDirectory> {
let mut user_dirs = Vec::new();
#[allow(deprecated)] let Some(_) = home_dir() else {
return user_dirs;
};
match std::env::consts::OS {
"linux" => {
user_dirs.push(ExistingUserDirectory {
install_type: ExistingInstallType::OfficialLauncher,
path: from_home_dir("Documents/My Games/FINAL FANTASY XIV - A Realm Reborn"),
});
user_dirs.push(ExistingUserDirectory {
install_type: ExistingInstallType::XIVLauncherCore,
path: from_home_dir(".xlcore/ffxivConfig"),
});
if let Ok(entries) = read_dir(from_home_dir(".local/share/astra/user/")) {
entries
.flatten()
.flat_map(|entry| {
let Ok(meta) = entry.metadata() else {
return vec![];
};
if meta.is_dir() {
return vec![entry.path()];
}
vec![]
})
.for_each(|path| {
user_dirs.push(ExistingUserDirectory {
install_type: ExistingInstallType::Astra,
path: path.into_os_string().into_string().unwrap(),
})
});
}
}
"macos" => {
user_dirs.push(ExistingUserDirectory {
install_type: ExistingInstallType::OfficialLauncher,
path: from_home_dir("Documents/My Games/FINAL FANTASY XIV - A Realm Reborn"),
})
}
"windows" => {
user_dirs.push(ExistingUserDirectory {
install_type: ExistingInstallType::OfficialLauncher,
path: from_home_dir("Documents/My Games/FINAL FANTASY XIV - A Realm Reborn"),
})
}
&_ => {}
}
user_dirs
.into_iter()
.filter(|dir| is_valid_user_dir(&dir.path))
.collect()
}
fn from_home_dir(path: &'static str) -> String {
#[allow(deprecated)] let mut new_path = home_dir().unwrap();
new_path.push(path);
new_path.into_os_string().into_string().unwrap()
}
fn is_valid_game_dir(path: &String) -> bool {
let mut d = PathBuf::from(path);
if fs::metadata(d.as_path()).is_err() {
return false;
}
d.push("game");
if fs::metadata(d.as_path()).is_err() {
return false;
}
d.pop();
d.push("boot");
if fs::metadata(d.as_path()).is_err() {
return false;
}
true
}
fn is_valid_user_dir(path: &String) -> bool {
let mut d = PathBuf::from(path);
if fs::metadata(d.as_path()).is_err() {
return false;
}
d.push("FFXIV.cfg");
if fs::metadata(d.as_path()).is_err() {
return false;
}
true
}