diff --git a/src-tauri/src/screamapi_config.rs b/src-tauri/src/screamapi_config.rs new file mode 100644 index 0000000..bd35aad --- /dev/null +++ b/src-tauri/src/screamapi_config.rs @@ -0,0 +1,137 @@ +use log::{info, warn}; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use std::fs; +use std::path::{Path, PathBuf}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct ScreamAPIConfig { + #[serde(rename = "$schema")] + pub schema: String, + #[serde(rename = "$version")] + pub version: u32, + pub logging: bool, + pub log_eos: bool, + pub block_metrics: bool, + pub namespace_id: String, + pub default_dlc_status: String, + pub override_dlc_status: HashMap, + pub extra_graphql_endpoints: Vec, + pub extra_entitlements: HashMap, +} + +impl Default for ScreamAPIConfig { + fn default() -> Self { + Self { + schema: "https://raw.githubusercontent.com/acidicoala/ScreamAPI/master/res/ScreamAPI.schema.json".to_string(), + version: 3, + logging: false, + log_eos: false, + block_metrics: false, + namespace_id: String::new(), + default_dlc_status: "unlocked".to_string(), + override_dlc_status: HashMap::new(), + extra_graphql_endpoints: Vec::new(), + extra_entitlements: HashMap::new(), + } + } +} + +/// Write a default ScreamAPI config to a specific directory. +/// Called internally by the installer when first setting up ScreamAPI. +pub fn write_default_config(dir: &Path) -> Result<(), String> { + write_config_to_dir(dir, &ScreamAPIConfig::default()) +} + +/// Write ScreamAPI config to a specific directory (where the ScreamAPI DLL lives) +pub fn write_config_to_dir(dir: &Path, config: &ScreamAPIConfig) -> Result<(), String> { + let config_path = dir.join("ScreamAPI.config.json"); + + let content = serde_json::to_string_pretty(config) + .map_err(|e| format!("Failed to serialize ScreamAPI config: {}", e))?; + + fs::write(&config_path, content) + .map_err(|e| format!("Failed to write ScreamAPI config: {}", e))?; + + info!("Wrote ScreamAPI config to: {}", config_path.display()); + Ok(()) +} + +/// Read ScreamAPI config from a game's install path. +/// Looks for EOSSDK backup files to find the directory. +pub fn read_config(game_path: &str) -> Result, String> { + let config_path = match find_screamapi_config_path(game_path) { + Some(p) => p, + None => return Ok(None), + }; + + if !config_path.exists() { + return Ok(None); + } + + let content = fs::read_to_string(&config_path) + .map_err(|e| format!("Failed to read ScreamAPI config: {}", e))?; + + let config: ScreamAPIConfig = serde_json::from_str(&content) + .map_err(|e| format!("Failed to parse ScreamAPI config: {}", e))?; + + info!("Read ScreamAPI config from: {}", config_path.display()); + Ok(Some(config)) +} + +/// Write ScreamAPI config to the directory where ScreamAPI DLLs are installed. +pub fn write_config(game_path: &str, config: &ScreamAPIConfig) -> Result<(), String> { + // Find existing config location or fall back to game root + let config_path = find_screamapi_config_path(game_path) + .unwrap_or_else(|| Path::new(game_path).join("ScreamAPI.config.json")); + + let content = serde_json::to_string_pretty(config) + .map_err(|e| format!("Failed to serialize ScreamAPI config: {}", e))?; + + fs::write(&config_path, content) + .map_err(|e| format!("Failed to write ScreamAPI config: {}", e))?; + + info!("Wrote ScreamAPI config to: {}", config_path.display()); + Ok(()) +} + +/// Delete ScreamAPI config from a game directory +pub fn delete_config(game_path: &str) -> Result<(), String> { + let config_path = match find_screamapi_config_path(game_path) { + Some(p) => p, + None => return Ok(()), + }; + + if config_path.exists() { + fs::remove_file(&config_path) + .map_err(|e| format!("Failed to delete ScreamAPI config: {}", e))?; + info!("Deleted ScreamAPI config from: {}", config_path.display()); + } + + Ok(()) +} + +/// Find where the ScreamAPI config should live by looking for EOSSDK backup files +/// (EOSSDK-Win64-Shipping_o.dll or EOSSDK-Win32-Shipping_o.dll) +fn find_screamapi_config_path(game_path: &str) -> Option { + use walkdir::WalkDir; + + for entry in WalkDir::new(game_path) + .max_depth(8) + .into_iter() + .filter_map(Result::ok) + { + let path = entry.path(); + let filename = path.file_name()?.to_string_lossy(); + + if (filename.starts_with("EOSSDK-Win") && filename.ends_with("_o.dll")) + || filename == "ScreamAPI.config.json" + { + let dir = path.parent()?; + return Some(dir.join("ScreamAPI.config.json")); + } + } + + warn!("Could not find ScreamAPI install dir in {}, using game root", game_path); + None +} \ No newline at end of file