diff --git a/Cargo.toml b/Cargo.toml index 6b80f84..82f8602 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "anime-launcher-sdk" -version = "0.5.3" +version = "0.5.4" authors = ["Nikita Podvirnyy "] license = "GPL-3.0" readme = "README.md" @@ -10,7 +10,7 @@ edition = "2021" anime-game-core = { path = "anime-game-core", features = ["genshin", "all"] } anyhow = "1.0" -dirs = "4.0.0" +dirs = "5.0.0" tracing = "0.1" cached = { version = "0.42", features = ["proc_macro"] } diff --git a/anime-game-core b/anime-game-core index e0245c4..c0bf96a 160000 --- a/anime-game-core +++ b/anime-game-core @@ -1 +1 @@ -Subproject commit e0245c40871f585781fd504fb14fd657b26cb4af +Subproject commit c0bf96ae96c8b5be37b5dc043d45c6819a23eac2 diff --git a/src/states.rs b/src/states.rs index 9cadd9a..4c7a02b 100644 --- a/src/states.rs +++ b/src/states.rs @@ -7,7 +7,6 @@ use wincompatlib::prelude::*; use serde::{Serialize, Deserialize}; -use crate::consts; use super::components::wine::WincompatlibWine; #[derive(Debug, Clone, Serialize, Deserialize)] @@ -20,7 +19,7 @@ pub enum LauncherState { voices: Vec }, - PatchAvailable(Patch), + MainPatchAvailable(UnityPlayerPatch), #[cfg(feature = "components")] WineNotInstalled, @@ -59,43 +58,48 @@ pub enum StateUpdating { Patch } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct LauncherStateParams { + pub wine_prefix: PathBuf, + pub game_path: PathBuf, + + pub selected_voices: Vec, + + pub patch_servers: Vec, + pub patch_folder: PathBuf, + pub use_xlua_patch: bool, + + pub status_updater: F +} + impl LauncherState { - #[tracing::instrument(level = "debug", skip(status), ret)] - pub fn get(wine_prefix: T, game_path: T, voices: Vec, patch_servers: Vec, status: F) -> anyhow::Result - where - T: Into + std::fmt::Debug, - F: Fn(StateUpdating), - S: ToString + std::fmt::Debug - { + pub fn get(params: LauncherStateParams) -> anyhow::Result { tracing::debug!("Trying to get launcher state"); - let wine_prefix = wine_prefix.into(); - let game_path = game_path.into(); - // Check prefix existence - if !wine_prefix.join("drive_c").exists() { + if !params.wine_prefix.join("drive_c").exists() { return Ok(Self::PrefixNotExists); } // Check game installation status - status(StateUpdating::Game); + (params.status_updater)(StateUpdating::Game); - let game = Game::new(&game_path); + let game = Game::new(¶ms.game_path); let diff = game.try_get_diff()?; Ok(match diff { VersionDiff::Latest(_) | VersionDiff::Predownload { .. } => { let mut predownload_voice = Vec::new(); - for locale in voices { + for locale in params.selected_voices { let mut voice_package = VoicePackage::with_locale(locale)?; - status(StateUpdating::Voice(voice_package.locale())); + (params.status_updater)(StateUpdating::Voice(voice_package.locale())); // Replace voice package struct with the one constructed in the game's folder // so it'll properly calculate its difference instead of saying "not installed" - if voice_package.is_installed_in(&game_path) { - voice_package = match VoicePackage::new(get_voice_package_path(&game_path, voice_package.locale())) { + if voice_package.is_installed_in(¶ms.game_path) { + voice_package = match VoicePackage::new(get_voice_package_path(¶ms.game_path, voice_package.locale())) { Some(locale) => locale, None => return Err(anyhow::anyhow!("Failed to load {} voice package", voice_package.locale().to_name())) }; @@ -113,11 +117,26 @@ impl LauncherState { } } - status(StateUpdating::Patch); + // Check game patch status + (params.status_updater)(StateUpdating::Patch); - let patch = Patch::try_fetch(patch_servers, consts::PATCH_FETCHING_TIMEOUT)?; + let patch = Patch::new(¶ms.patch_folder); + + // Sync local patch folder with remote if needed + if patch.is_sync(¶ms.patch_servers)?.is_none() { + for server in ¶ms.patch_servers { + if let Ok(true) = patch.sync(server) { + break; + } + } + } + + // Check UnityPlayer patch + let main_patch = patch.unity_player_patch()?; + + if main_patch.is_applied(¶ms.game_path)? { + // TODO: add Xlua patch check - if patch.is_applied(&game_path)? { if let VersionDiff::Predownload { .. } = diff { Self::PredownloadAvailable { game: diff, @@ -131,7 +150,7 @@ impl LauncherState { } else { - Self::PatchAvailable(patch) + Self::MainPatchAvailable(main_patch) } } @@ -142,8 +161,8 @@ impl LauncherState { } #[cfg(feature = "config")] - #[tracing::instrument(level = "debug", skip(status), ret)] - pub fn get_from_config(status: T) -> anyhow::Result { + #[tracing::instrument(level = "debug", skip(status_updater), ret)] + pub fn get_from_config(status_updater: T) -> anyhow::Result { tracing::debug!("Trying to get launcher state"); let config = crate::config::get()?; @@ -187,6 +206,17 @@ impl LauncherState { }); } - Self::get(wine_prefix, config.game.path, voices, config.patch.servers, status) + Self::get(LauncherStateParams { + wine_prefix, + game_path: config.game.path, + + selected_voices: voices, + + patch_servers: config.patch.servers, + patch_folder: config.patch.path, + use_xlua_patch: false, // TODO + + status_updater + }) } }