use anyhow::Result;
use larian_formats::bg3::Save;
use std::{
borrow::Cow,
fs::{File, OpenOptions},
io::{BufReader, Write},
os::unix::fs::PermissionsExt,
path::{Path, PathBuf},
sync::OnceLock,
};
pub const DEFAULT_APP_DATA_DIR: &str =
"~/.local/share/Steam/steamapps/compatdata/1086940/pfx/drive_c/users/steamuser/AppData";
static APP_DATA_DIR: OnceLock<String> = OnceLock::new();
static MODS_PATH: OnceLock<PathBuf> = OnceLock::new();
static SETTINGS_PATH: OnceLock<PathBuf> = OnceLock::new();
pub fn open_mod_settings_file(app_data_path: &str) -> Result<File> {
let file = File::open(settings_file_path(app_data_path))?;
Ok(file)
}
pub fn read_current_installed_mods(app_data_path: &str) -> Result<Save> {
let settings_file = open_mod_settings_file(app_data_path)?;
let parsed_settings = quick_xml::de::from_reader(BufReader::new(settings_file))?;
Ok(parsed_settings)
}
pub fn write_file(
path: impl AsRef<Path>,
contents: impl AsRef<[u8]>,
is_readonly: bool,
) -> Result<()> {
if is_readonly {
let file = File::open(path.as_ref())?;
let mut permissions = file.metadata()?.permissions();
permissions.set_mode(permissions.mode() | 0o600);
file.set_permissions(permissions)?;
}
let mut file = OpenOptions::new()
.write(true)
.truncate(true)
.create(true)
.open(&path)?;
file.write_all(contents.as_ref())?;
if is_readonly {
let mut permissions = file.metadata()?.permissions();
permissions.set_readonly(true);
file.set_permissions(permissions)?;
}
Ok(())
}
pub fn app_data_dir(app_data_path: &str) -> &'static str {
APP_DATA_DIR.get_or_init(|| {
let app_data_path = match std::env::var("HOME") {
Ok(home_dir) if app_data_path.starts_with('~') => {
Cow::Owned(app_data_path.replacen('~', &home_dir, 1))
}
_ => Cow::Borrowed(app_data_path),
};
app_data_path.into_owned()
})
}
pub fn mods_directory_path(app_data_path: &str) -> &'static PathBuf {
MODS_PATH.get_or_init(|| {
[
app_data_dir(app_data_path),
"Local",
"Larian Studios",
"Baldur's Gate 3",
"Mods",
]
.into_iter()
.collect()
})
}
pub fn settings_file_path(app_data_path: &str) -> &'static PathBuf {
SETTINGS_PATH.get_or_init(|| {
[
app_data_dir(app_data_path),
"Local",
"Larian Studios",
"Baldur's Gate 3",
"PlayerProfiles",
"Public",
"modsettings.lsx",
]
.into_iter()
.collect()
})
}