diff --git a/Cargo.toml b/Cargo.toml index 5e48f8e..30c69e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" [dependencies.anime-game-core] git = "https://github.com/an-anime-team/anime-game-core" -tag = "1.11.8" +tag = "1.12.0" features = ["all"] # path = "../anime-game-core" # ! for dev purposes only @@ -35,6 +35,10 @@ star-rail = ["anime-game-core/star-rail"] honkai = ["anime-game-core/honkai"] pgr = ["anime-game-core/pgr"] +genshin-patch = ["anime-game-core/patch-dawn"] +star-rail-patch = ["anime-game-core/patch-jadeite"] +honkai-patch = ["anime-game-core/patch-jadeite"] + # Common features states = [] config = ["dep:serde", "dep:serde_json", "dep:enum-ordinalize"] diff --git a/src/games/star_rail/config/schema/patch.rs b/src/games/star_rail/config/schema/patch.rs index a0f221b..9b15e8d 100644 --- a/src/games/star_rail/config/schema/patch.rs +++ b/src/games/star_rail/config/schema/patch.rs @@ -7,9 +7,7 @@ use crate::star_rail::consts::launcher_dir; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Patch { - pub path: PathBuf, - pub servers: Vec, - pub root: bool + pub path: PathBuf } impl Default for Patch { @@ -18,15 +16,7 @@ impl Default for Patch { let launcher_dir = launcher_dir().expect("Failed to get launcher dir"); Self { - path: launcher_dir.join("patch"), - - servers: vec![ - String::from("https://codeberg.org/an-anime-team/astra"), - String::from("https://notabug.org/mkrsym1/astra") - ], - - // Disable root requirement for patching if we're running launcher in flatpak - root: !PathBuf::from("/.flatpak-info").exists() + path: launcher_dir.join("patch") } } } @@ -36,35 +26,9 @@ impl From<&JsonValue> for Patch { let default = Self::default(); Self { - path: match value.get("path") { - Some(value) => match value.as_str() { - Some(value) => PathBuf::from(value), - None => default.path - }, + path: match value.get("path").and_then(|path| path.as_str()).map(PathBuf::from) { + Some(path) => path, None => default.path - }, - - servers: match value.get("servers") { - Some(value) => match value.as_array() { - Some(values) => { - let mut servers = Vec::new(); - - for value in values { - if let Some(server) = value.as_str() { - servers.push(server.to_string()); - } - } - - servers - }, - None => default.servers - }, - None => default.servers - }, - - root: match value.get("root") { - Some(value) => value.as_bool().unwrap_or(default.root), - None => default.root } } } diff --git a/src/games/star_rail/game.rs b/src/games/star_rail/game.rs index 95e09fa..b4ea8f7 100644 --- a/src/games/star_rail/game.rs +++ b/src/games/star_rail/game.rs @@ -24,6 +24,7 @@ struct Folders { pub wine: PathBuf, pub prefix: PathBuf, pub game: PathBuf, + pub patch: PathBuf, pub temp: PathBuf } @@ -34,6 +35,7 @@ fn replace_keywords(command: impl ToString, folders: &Folders) -> String { .replace("%temp%", folders.game.to_str().unwrap()) .replace("%launcher%", &consts::launcher_dir().unwrap().to_string_lossy()) .replace("%game%", folders.temp.to_str().unwrap()) + .replace("%patch%", folders.patch.to_str().unwrap()) } /// Try to run the game @@ -60,6 +62,7 @@ pub fn run() -> anyhow::Result<()> { wine: config.game.wine.builds.join(&wine.name), prefix: config.game.wine.prefix.clone(), game: game_path.clone(), + patch: config.patch.path.clone(), temp: config.launcher.temp.clone().unwrap_or(std::env::temp_dir()) }; @@ -92,7 +95,7 @@ pub fn run() -> anyhow::Result<()> { windows_command += " "; } - windows_command += "launch.bat "; + windows_command += &format!("'{}/jadeite.exe' 'Z:\\{}/StarRail.exe' ", folders.patch.to_string_lossy(), folders.game.to_string_lossy()); if config.game.wine.borderless { windows_command += "-screen-fullscreen 0 -popupwindow "; @@ -124,10 +127,13 @@ pub fn run() -> anyhow::Result<()> { folders.game.to_str().unwrap() ); + let bwrap = format!("{bwrap} --bind '{}' /tmp/sandbox/patch", folders.patch.to_string_lossy()); + let sandboxed_folders = Folders { wine: PathBuf::from("/tmp/sandbox/wine"), prefix: PathBuf::from("/tmp/sandbox/prefix"), game: PathBuf::from("/tmp/sandbox/game"), + patch: PathBuf::from("/tmp/sandbox/patch"), temp: PathBuf::from("/tmp") }; @@ -135,6 +141,14 @@ pub fn run() -> anyhow::Result<()> { .replace(folders.wine.to_str().unwrap(), sandboxed_folders.wine.to_str().unwrap()) .replace(folders.prefix.to_str().unwrap(), sandboxed_folders.prefix.to_str().unwrap()) .replace(folders.game.to_str().unwrap(), sandboxed_folders.game.to_str().unwrap()) + .replace(folders.patch.to_str().unwrap(), sandboxed_folders.patch.to_str().unwrap()) + .replace(folders.temp.to_str().unwrap(), sandboxed_folders.temp.to_str().unwrap()); + + windows_command = windows_command + .replace(folders.wine.to_str().unwrap(), sandboxed_folders.wine.to_str().unwrap()) + .replace(folders.prefix.to_str().unwrap(), sandboxed_folders.prefix.to_str().unwrap()) + .replace(folders.game.to_str().unwrap(), sandboxed_folders.game.to_str().unwrap()) + .replace(folders.patch.to_str().unwrap(), sandboxed_folders.patch.to_str().unwrap()) .replace(folders.temp.to_str().unwrap(), sandboxed_folders.temp.to_str().unwrap()); bash_command = format!("{bwrap} --chdir /tmp/sandbox/game -- {bash_command}"); diff --git a/src/games/star_rail/states.rs b/src/games/star_rail/states.rs index a0509a9..b2ddfc6 100644 --- a/src/games/star_rail/states.rs +++ b/src/games/star_rail/states.rs @@ -10,16 +10,21 @@ use crate::star_rail::config::Config; pub enum LauncherState { Launch, - /// Always contains `VersionDiff::Predownload` - PredownloadAvailable(VersionDiff), + PatchNotVerified, + PatchBroken, + PatchUnsafe, - MainPatchAvailable(MainPatch), + PatchNotInstalled, + PatchUpdateAvailable, #[cfg(feature = "components")] WineNotInstalled, PrefixNotExists, + /// Always contains `VersionDiff::Predownload` + PredownloadAvailable(VersionDiff), + // Always contains `VersionDiff::Diff` GameUpdateAvailable(VersionDiff), @@ -42,8 +47,6 @@ pub struct LauncherStateParams { pub game_edition: GameEdition, pub wine_prefix: PathBuf, - - pub patch_servers: Vec, pub patch_folder: PathBuf, pub status_updater: F @@ -65,37 +68,34 @@ impl LauncherState { let diff = game.try_get_diff()?; match diff { - VersionDiff::Latest { .. } | VersionDiff::Predownload { .. } => { + VersionDiff::Latest { version, .. } | VersionDiff::Predownload { current: version, .. } => { // Check game patch status (params.status_updater)(StateUpdating::Patch); - let patch = Patch::new(¶ms.patch_folder, params.game_edition); + if !jadeite::is_installed(¶ms.patch_folder) { + return Ok(Self::PatchNotInstalled); + } - // Sync local patch folder with remote if needed - // TODO: maybe I shouldn't do it here? - if patch.is_sync(¶ms.patch_servers)?.is_none() { - for server in ¶ms.patch_servers { - if patch.sync(server).is_ok() { - break; + if jadeite::get_latest()?.version > jadeite::get_version(params.patch_folder)? { + return Ok(Self::PatchUpdateAvailable); + } + + match jadeite::get_metadata()?.hsr.global.get_status(version) { + JadeitePatchStatusVariant::Verified => { + // Check if update predownload available + if let VersionDiff::Predownload { .. } = diff { + Ok(Self::PredownloadAvailable(diff)) + } + + // Otherwise we can launch the game + else { + Ok(Self::Launch) } } - } - // Check the main patch - let main_patch = patch.main_patch()?; - - if !main_patch.is_applied(¶ms.game_path)? { - return Ok(Self::MainPatchAvailable(main_patch)); - } - - // Check if update predownload available - if let VersionDiff::Predownload { .. } = diff { - Ok(Self::PredownloadAvailable(diff)) - } - - // Otherwise we can launch the game - else { - Ok(Self::Launch) + JadeitePatchStatusVariant::Unverified => Ok(Self::PatchNotVerified), + JadeitePatchStatusVariant::Broken => Ok(Self::PatchBroken), + JadeitePatchStatusVariant::Unsafe => Ok(Self::PatchUnsafe) } } @@ -126,8 +126,6 @@ impl LauncherState { game_edition: config.launcher.edition, wine_prefix: config.get_wine_prefix_path(), - - patch_servers: config.patch.servers, patch_folder: config.patch.path, status_updater