diff --git a/src/error.rs b/src/error.rs index 3b6cd87..ced46c5 100644 --- a/src/error.rs +++ b/src/error.rs @@ -74,11 +74,13 @@ pub enum Error { )] InstallerNotExecutable, - #[error(" + #[error( + " The installer '{package_id}' does not support the current tcli installer protocol. Expected: {our_version:#?} Recieved: {given_version:#?} - ")] + " + )] InstallerBadVersion { package_id: String, given_version: Version, @@ -94,7 +96,9 @@ pub enum Error { #[error("The installer returned an error:\n\t{message}")] InstallerError { message: String }, - #[error("The provided game id '{0}' does not exist or has not been imported into this profile.")] + #[error( + "The provided game id '{0}' does not exist or has not been imported into this profile." + )] BadGameId(String), #[error("The Steam app with id '{0}' could not be found.")] diff --git a/src/game/import/ea.rs b/src/game/import/ea.rs index 3909a25..595fbaa 100644 --- a/src/game/import/ea.rs +++ b/src/game/import/ea.rs @@ -1,13 +1,12 @@ use std::path::PathBuf; +use super::{Error, GameImporter}; use crate::game::import::ImportBase; use crate::game::registry::{ActiveDistribution, GameData}; use crate::ts::v1::models::ecosystem::GameDefPlatform; use crate::util::reg::{self, HKey}; -use super::{Error, GameImporter}; - -pub struct EaImporter { +pub struct EaImporter { ident: String, } @@ -25,20 +24,22 @@ impl GameImporter for EaImporter { let value = reg::get_value_at(HKey::LocalMachine, &subkey, "Install Dir")?; let game_dir = PathBuf::from(value); - let r2mm = base - .game_def - .r2modman - .as_ref() - .expect("Expected a valid r2mm field in the ecosystem schema, got nothing. This is a bug."); + let r2mm = base.game_def.r2modman.as_ref().expect( + "Expected a valid r2mm field in the ecosystem schema, got nothing. This is a bug.", + ); let exe_path = base .overrides .custom_exe .clone() .or_else(|| super::find_game_exe(&r2mm.exe_names, &game_dir)) - .ok_or_else(|| super::Error::ExeNotFound(base.game_def.label.clone(), game_dir.clone()))?; + .ok_or_else(|| { + super::Error::ExeNotFound(base.game_def.label.clone(), game_dir.clone()) + })?; let dist = ActiveDistribution { - dist: GameDefPlatform::Origin { identifier: self.ident.to_string() }, + dist: GameDefPlatform::Origin { + identifier: self.ident.to_string(), + }, game_dir: game_dir.to_path_buf(), data_dir: game_dir.join(&r2mm.data_folder_name), exe_path, diff --git a/src/game/import/egs.rs b/src/game/import/egs.rs index 6d2bffe..d73c443 100644 --- a/src/game/import/egs.rs +++ b/src/game/import/egs.rs @@ -1,13 +1,13 @@ use std::fs; use std::path::PathBuf; + use serde::{Deserialize, Serialize}; +use super::{Error, GameImporter, ImportBase}; use crate::game::registry::{ActiveDistribution, GameData}; use crate::ts::v1::models::ecosystem::GameDefPlatform; use crate::util::reg::{self, HKey}; -use super::{Error, GameImporter, ImportBase}; - #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "PascalCase")] struct PartialInstallManifest { @@ -15,7 +15,7 @@ struct PartialInstallManifest { app_name: String, } -pub struct EgsImporter { +pub struct EgsImporter { ident: String, } @@ -55,29 +55,33 @@ impl GameImporter for EgsImporter { .collect::>(); // Search for the manifest which contains the correct game AppName. - let game_dir = manifest_files.into_iter().find_map(|x| { - let file_contents = fs::read_to_string(x).unwrap(); - let manifest: PartialInstallManifest = serde_json::from_str(&file_contents).unwrap(); + let game_dir = manifest_files + .into_iter() + .find_map(|x| { + let file_contents = fs::read_to_string(x).unwrap(); + let manifest: PartialInstallManifest = + serde_json::from_str(&file_contents).unwrap(); - if manifest.app_name == self.ident { - Some(manifest.install_location) - } else { - None - } - }).ok_or_else(|| super::Error::NotFound(game_label.clone(), "EGS".to_string()))?; + if manifest.app_name == self.ident { + Some(manifest.install_location) + } else { + None + } + }) + .ok_or_else(|| super::Error::NotFound(game_label.clone(), "EGS".to_string()))?; - let r2mm = base - .game_def - .r2modman - .as_ref() - .expect("Expected a valid r2mm field in the ecosystem schema, got nothing. This is a bug."); + let r2mm = base.game_def.r2modman.as_ref().expect( + "Expected a valid r2mm field in the ecosystem schema, got nothing. This is a bug.", + ); let exe_path = base .overrides .custom_exe .clone() .or_else(|| super::find_game_exe(&r2mm.exe_names, &game_dir)) - .ok_or_else(|| super::Error::ExeNotFound(base.game_def.label.clone(), game_dir.clone()))?; + .ok_or_else(|| { + super::Error::ExeNotFound(base.game_def.label.clone(), game_dir.clone()) + })?; let dist = ActiveDistribution { dist: GameDefPlatform::Other, game_dir: game_dir.to_path_buf(), diff --git a/src/game/import/gamepass.rs b/src/game/import/gamepass.rs index a7fc8c4..75cc626 100644 --- a/src/game/import/gamepass.rs +++ b/src/game/import/gamepass.rs @@ -1,11 +1,10 @@ use std::path::PathBuf; +use super::Error; +use super::{GameImporter, ImportBase}; +use crate::game::registry::{ActiveDistribution, GameData}; use crate::ts::v1::models::ecosystem::GameDefPlatform; use crate::util::reg::{self, HKey}; -use crate::game::registry::{ActiveDistribution, GameData}; - -use super::{GameImporter, ImportBase}; -use super::Error; pub struct GamepassImporter { ident: String, @@ -26,30 +25,36 @@ impl GameImporter for GamepassImporter { let uuid = reg::get_values_at(HKey::LocalMachine, &format!("{root}\\Package\\"))? .into_iter() .find(|x| x.key.starts_with(&self.ident)) - .ok_or_else(|| super::Error::NotFound(base.game_def.label.clone(), "Gamepass".to_string()))? + .ok_or_else(|| { + super::Error::NotFound(base.game_def.label.clone(), "Gamepass".to_string()) + })? .val .replace('\"', ""); let game_root = reg::get_keys_at(HKey::LocalMachine, &format!("Root\\{}\\", uuid))? .into_iter() .next() - .ok_or_else(|| super::Error::NotFound(base.game_def.label.clone(), "Gamepass".to_string()))?; + .ok_or_else(|| { + super::Error::NotFound(base.game_def.label.clone(), "Gamepass".to_string()) + })?; let game_dir = PathBuf::from(reg::get_value_at(HKey::LocalMachine, &game_root, "Root")?); - let r2mm = base - .game_def - .r2modman - .as_ref() - .expect("Expected a valid r2mm field in the ecosystem schema, got nothing. This is a bug."); + let r2mm = base.game_def.r2modman.as_ref().expect( + "Expected a valid r2mm field in the ecosystem schema, got nothing. This is a bug.", + ); let exe_path = base .overrides .custom_exe .clone() .or_else(|| super::find_game_exe(&r2mm.exe_names, &game_dir)) - .ok_or_else(|| super::Error::ExeNotFound(base.game_def.label.clone(), game_dir.clone()))?; + .ok_or_else(|| { + super::Error::ExeNotFound(base.game_def.label.clone(), game_dir.clone()) + })?; let dist = ActiveDistribution { - dist: GameDefPlatform::GamePass { identifier: self.ident.to_string() }, + dist: GameDefPlatform::GamePass { + identifier: self.ident.to_string(), + }, game_dir: game_dir.to_path_buf(), data_dir: game_dir.join(&r2mm.data_folder_name), exe_path, @@ -57,4 +62,4 @@ impl GameImporter for GamepassImporter { Ok(super::construct_data(base, dist)) } -} \ No newline at end of file +} diff --git a/src/game/import/mod.rs b/src/game/import/mod.rs index 526f74d..f99f881 100644 --- a/src/game/import/mod.rs +++ b/src/game/import/mod.rs @@ -6,16 +6,15 @@ pub mod steam; use std::path::{Path, PathBuf}; +use super::registry::{ActiveDistribution, GameData}; use crate::game::import::ea::EaImporter; use crate::game::import::egs::EgsImporter; use crate::game::import::gamepass::GamepassImporter; use crate::game::import::steam::SteamImporter; -use crate::ts::v1::{ecosystem, models::ecosystem::GameDefPlatform}; use crate::ts::v1::models::ecosystem::GameDef; +use crate::ts::v1::{ecosystem, models::ecosystem::GameDefPlatform}; use crate::util::reg; -use super::registry::{ActiveDistribution, GameData}; - #[derive(thiserror::Error, Debug)] pub enum Error { #[error("The game '{0}' is not supported by platform '{1}'.")] @@ -87,10 +86,7 @@ impl ImportBase { } pub fn with_overrides(self, overrides: ImportOverrides) -> Self { - ImportBase { - overrides, - ..self - } + ImportBase { overrides, ..self } } pub fn with_wine_prefix(self, wine_prefix: Option) -> Self { @@ -102,16 +98,25 @@ impl ImportBase { } pub fn select_importer(base: &ImportBase) -> Result, Error> { - base - .game_def + base.game_def .distributions .iter() .find_map(|dist| match dist { - GameDefPlatform::Origin { identifier } => Some(Box::new(EaImporter::new(identifier)) as _), - GameDefPlatform::EpicGames { identifier } => Some(Box::new(EgsImporter::new(identifier)) as _), - GameDefPlatform::GamePass { identifier } => Some(Box::new(GamepassImporter::new(identifier)) as _), - GameDefPlatform::Steam { identifier } => Some(Box::new(SteamImporter::new(identifier)) as _), - GameDefPlatform::SteamDirect { identifier } => Some(Box::new(SteamImporter::new(identifier)) as _), + GameDefPlatform::Origin { identifier } => { + Some(Box::new(EaImporter::new(identifier)) as _) + } + GameDefPlatform::EpicGames { identifier } => { + Some(Box::new(EgsImporter::new(identifier)) as _) + } + GameDefPlatform::GamePass { identifier } => { + Some(Box::new(GamepassImporter::new(identifier)) as _) + } + GameDefPlatform::Steam { identifier } => { + Some(Box::new(SteamImporter::new(identifier)) as _) + } + GameDefPlatform::SteamDirect { identifier } => { + Some(Box::new(SteamImporter::new(identifier)) as _) + } _ => None, }) .ok_or_else(|| Error::NotSupported(base.game_id.clone(), "".into())) @@ -126,9 +131,15 @@ pub fn find_game_exe(possible: &[String], base_path: &Path) -> Option { pub fn construct_data(base: ImportBase, dist: ActiveDistribution) -> GameData { GameData { - identifier: base.overrides.custom_id.unwrap_or(base.game_def.label.clone()), + identifier: base + .overrides + .custom_id + .unwrap_or(base.game_def.label.clone()), ecosystem_label: base.game_def.label, - display_name: base.overrides.custom_name.unwrap_or(base.game_def.meta.display_name), + display_name: base + .overrides + .custom_name + .unwrap_or(base.game_def.meta.display_name), active_distribution: dist, possible_distributions: base.game_def.distributions, } diff --git a/src/game/import/nodrm.rs b/src/game/import/nodrm.rs index 982d4a6..5e07db4 100644 --- a/src/game/import/nodrm.rs +++ b/src/game/import/nodrm.rs @@ -1,11 +1,10 @@ use std::path::{Path, PathBuf}; +use super::{Error, GameImporter, ImportBase}; use crate::game::registry::{ActiveDistribution, GameData}; use crate::ts::v1::models::ecosystem::GameDefPlatform; -use super::{Error, GameImporter, ImportBase}; - -pub struct NoDrmImporter { +pub struct NoDrmImporter { game_dir: PathBuf, } @@ -23,18 +22,18 @@ impl GameImporter for NoDrmImporter { Err(Error::DirNotFound(self.game_dir.to_path_buf()))?; } - let r2mm = base - .game_def - .r2modman - .as_ref() - .expect("Expected a valid r2mm field in the ecosystem schema, got nothing. This is a bug."); + let r2mm = base.game_def.r2modman.as_ref().expect( + "Expected a valid r2mm field in the ecosystem schema, got nothing. This is a bug.", + ); let exe_path = base .overrides .custom_exe .clone() .or_else(|| super::find_game_exe(&r2mm.exe_names, &self.game_dir)) - .ok_or_else(|| super::Error::ExeNotFound(base.game_def.label.clone(), self.game_dir.clone()))?; + .ok_or_else(|| { + super::Error::ExeNotFound(base.game_def.label.clone(), self.game_dir.clone()) + })?; let dist = ActiveDistribution { dist: GameDefPlatform::Other, game_dir: self.game_dir.to_path_buf(), diff --git a/src/game/import/steam.rs b/src/game/import/steam.rs index 1fccc9c..bab687e 100644 --- a/src/game/import/steam.rs +++ b/src/game/import/steam.rs @@ -1,11 +1,10 @@ use std::path::PathBuf; -use crate::game::registry::{ActiveDistribution, GameData}; -use crate::ts::v1::models::ecosystem::GameDefPlatform; +use steamlocate::SteamDir; use super::{Error, GameImporter, ImportBase}; - -use steamlocate::SteamDir; +use crate::game::registry::{ActiveDistribution, GameData}; +use crate::ts::v1::models::ecosystem::GameDefPlatform; pub struct SteamImporter { appid: u32, @@ -16,21 +15,20 @@ impl SteamImporter { pub fn new(appid: &str) -> Self { SteamImporter { steam_dir: None, - appid: appid.parse::().expect("Got a bad appid from the ecosystem schema. This is a bug"), + appid: appid + .parse::() + .expect("Got a bad appid from the ecosystem schema. This is a bug"), } } pub fn with_steam_dir(self, steam_dir: Option) -> Self { - SteamImporter { - steam_dir, - ..self - } + SteamImporter { steam_dir, ..self } } } impl GameImporter for SteamImporter { fn construct(self: Box, base: ImportBase) -> Result { - // If an app_dir is provided then we can skip automatic path resolution. If not, + // If an app_dir is provided then we can skip automatic path resolution. If not, // attempt to resolve the app's directory from the steam dir, whether provided or otherwise. let app_dir = match base.overrides.game_dir { Some(ref game_dir) => game_dir.clone(), @@ -40,15 +38,24 @@ impl GameImporter for SteamImporter { .as_ref() .map_or_else(SteamDir::locate, |x| SteamDir::from_dir(x)) .map_err(|e: steamlocate::Error| match e { - steamlocate::Error::InvalidSteamDir(_) => Error::SteamDirBadPath(self.steam_dir.as_ref().unwrap().to_path_buf()), + steamlocate::Error::InvalidSteamDir(_) => { + Error::SteamDirBadPath(self.steam_dir.as_ref().unwrap().to_path_buf()) + } steamlocate::Error::FailedLocate(_) => Error::SteamDirNotFound, _ => unreachable!(), - })?; + })?; let (app, lib) = steam - .find_app(self.appid) - .unwrap_or_else(|e| panic!("An error occured while searching for app with id '{}': {e:?}.", self.appid)) - .ok_or_else(|| Error::SteamAppNotFound(self.appid, steam.path().to_path_buf()))?; + .find_app(self.appid) + .unwrap_or_else(|e| { + panic!( + "An error occured while searching for app with id '{}': {e:?}.", + self.appid + ) + }) + .ok_or_else(|| { + Error::SteamAppNotFound(self.appid, steam.path().to_path_buf()) + })?; lib.resolve_app_dir(&app) } }; @@ -57,18 +64,18 @@ impl GameImporter for SteamImporter { Err(Error::SteamDirNotFound)?; } - let r2mm = base - .game_def - .r2modman - .as_ref() - .expect("Expected a valid r2mm field in the ecosystem schema, got nothing. This is a bug."); + let r2mm = base.game_def.r2modman.as_ref().expect( + "Expected a valid r2mm field in the ecosystem schema, got nothing. This is a bug.", + ); let exe_path = r2mm .exe_names .iter() .map(|x| app_dir.join(x)) .find(|x| x.is_file()) - .ok_or_else(|| super::Error::ExeNotFound(base.game_def.label.clone(), app_dir.clone()))?; + .ok_or_else(|| { + super::Error::ExeNotFound(base.game_def.label.clone(), app_dir.clone()) + })?; let dist = ActiveDistribution { dist: GameDefPlatform::Steam { diff --git a/src/game/mod.rs b/src/game/mod.rs index 5ab4341..85e1eea 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -1,4 +1,4 @@ pub mod ecosystem; -pub mod registry; -pub mod proc; pub mod import; +pub mod proc; +pub mod registry; diff --git a/src/game/registry.rs b/src/game/registry.rs index 7fc7f2a..45a9d3c 100644 --- a/src/game/registry.rs +++ b/src/game/registry.rs @@ -78,4 +78,3 @@ pub fn write_data(game_registry: &Path, data: GameData) -> Result<(), Error> { Ok(()) } - diff --git a/src/ts/v1/models/ecosystem.rs b/src/ts/v1/models/ecosystem.rs index 88bf42e..6ee1a67 100644 --- a/src/ts/v1/models/ecosystem.rs +++ b/src/ts/v1/models/ecosystem.rs @@ -56,15 +56,19 @@ pub enum GameDefPlatform { } impl GameDefPlatform { - /// Hardcoding these for now until we integrate this sorta thing into + /// Hardcoding these for now until we integrate this sorta thing into /// the ecosystem schema, preferably as a compile time check. pub fn ident_from_name<'a>(&'a self, name: &str) -> Option<&'a str> { match self { GameDefPlatform::EpicGames { identifier } if name == "egs" => Some(identifier), GameDefPlatform::GamePass { identifier } if name == "gamepass" => Some(identifier), - GameDefPlatform::Origin { identifier } if name == "origin" || name == "ea" => Some(identifier), + GameDefPlatform::Origin { identifier } if name == "origin" || name == "ea" => { + Some(identifier) + } GameDefPlatform::Steam { identifier } if name == "steam" => Some(identifier), - GameDefPlatform::SteamDirect { identifier } if name == "steam-direct" => Some(identifier), + GameDefPlatform::SteamDirect { identifier } if name == "steam-direct" => { + Some(identifier) + } _ => None, } } @@ -78,7 +82,7 @@ impl GameDefPlatform { "steam-direct", "oculus", "other", - ] + ] } } diff --git a/src/util/mod.rs b/src/util/mod.rs index 9700edc..b3c8091 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,5 +1,5 @@ -pub mod os; pub mod file; +pub mod os; pub mod reg; mod temp_file; diff --git a/src/util/reg.rs b/src/util/reg.rs index 0fed7a9..df39b19 100644 --- a/src/util/reg.rs +++ b/src/util/reg.rs @@ -36,7 +36,10 @@ pub fn get_values_at(hkey: HKey, subkey: &str) -> Result, Error> open_subkey(hkey, subkey)? .enum_values() .map(|x| match x { - Ok((key, val)) => Ok(RegKeyVal { key, val: val.to_string() }), + Ok((key, val)) => Ok(RegKeyVal { + key, + val: val.to_string(), + }), Err(e) => Err(e), }) .collect::, _>>() @@ -45,5 +48,7 @@ pub fn get_values_at(hkey: HKey, subkey: &str) -> Result, Error> fn open_subkey(hkey: HKey, subkey: &str) -> Result { let local = RegKey::predef(hkey as _); - local.open_subkey(subkey).map_err(|_| Error::RegistrySubkeyRead(subkey.to_string())) + local + .open_subkey(subkey) + .map_err(|_| Error::RegistrySubkeyRead(subkey.to_string())) }