diff --git a/Cargo.lock b/Cargo.lock index 74b0dbe..ba92d25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,7 +31,7 @@ dependencies = [ [[package]] name = "anime-game-core" -version = "0.5.2" +version = "1.0.2" dependencies = [ "anyhow", "bzip2", diff --git a/anime-game-core b/anime-game-core index 2206e00..1254126 160000 --- a/anime-game-core +++ b/anime-game-core @@ -1 +1 @@ -Subproject commit 2206e00a963a3e1421a9d45d8f71f32a5c9b7acb +Subproject commit 12541266d567f3459430ba37e12b0d809d12733d diff --git a/blueprint-compiler b/blueprint-compiler index 59283a7..6ad1433 160000 --- a/blueprint-compiler +++ b/blueprint-compiler @@ -1 +1 @@ -Subproject commit 59283a76adc8d270ff5f67b630b7dfa905ec34a9 +Subproject commit 6ad1433587fa487e0d72c545178a61f8961c3b21 diff --git a/src/lib/config/game/dxvk.rs b/src/lib/config/game/dxvk.rs index a566f0a..aebee5c 100644 --- a/src/lib/config/game/dxvk.rs +++ b/src/lib/config/game/dxvk.rs @@ -5,8 +5,7 @@ use crate::lib::consts::launcher_dir; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Dxvk { - pub builds: String, - pub selected: Option + pub builds: String } impl Default for Dxvk { @@ -14,8 +13,7 @@ impl Default for Dxvk { let launcher_dir = launcher_dir().expect("Failed to get launcher dir"); Self { - builds: format!("{launcher_dir}/dxvks"), - selected: None + builds: format!("{launcher_dir}/dxvks") } } } @@ -28,20 +26,6 @@ impl From<&JsonValue> for Dxvk { builds: match value.get("builds") { Some(value) => value.as_str().unwrap_or(&default.builds).to_string(), None => default.builds - }, - - selected: match value.get("selected") { - Some(value) => { - if value.is_null() { - None - } else { - match value.as_str() { - Some(value) => Some(value.to_string()), - None => default.selected - } - } - }, - None => default.selected } } } diff --git a/src/lib/config/launcher/mod.rs b/src/lib/config/launcher/mod.rs index 895c26e..9b7a1d7 100644 --- a/src/lib/config/launcher/mod.rs +++ b/src/lib/config/launcher/mod.rs @@ -63,6 +63,7 @@ impl From for GameEdition { pub struct Launcher { pub language: String, pub temp: Option, + pub speed_limit: u64, pub repairer: Repairer, pub edition: GameEdition } @@ -72,6 +73,7 @@ impl Default for Launcher { Self { language: String::from("en-us"), temp: launcher_dir(), + speed_limit: 0, repairer: Repairer::default(), edition: GameEdition::default() } @@ -102,6 +104,11 @@ impl From<&JsonValue> for Launcher { None => default.temp }, + speed_limit: match value.get("speed_limit") { + Some(value) => value.as_u64().unwrap_or(default.speed_limit), + None => default.speed_limit + }, + repairer: match value.get("repairer") { Some(value) => Repairer::from(value), None => default.repairer diff --git a/src/lib/config/mod.rs b/src/lib/config/mod.rs index f9f2022..50db4fb 100644 --- a/src/lib/config/mod.rs +++ b/src/lib/config/mod.rs @@ -12,6 +12,10 @@ use super::wine::{ Version as WineVersion, List as WineList }; +use super::dxvk::{ + Version as DxvkVersion, + List as DxvkList +}; pub mod launcher; pub mod game; @@ -135,15 +139,10 @@ impl Config { pub fn try_get_selected_wine_info(&self) -> Option { match &self.game.wine.selected { Some(selected) => { - for group in WineList::get() { - for version in group.versions { - if &version.name == selected { - return Some(version.clone()); - } - } - } - - None + WineList::get().iter() + .flat_map(|group| group.versions.clone()) + .filter(|version| version.name.eq(selected)) + .next() }, None => None } @@ -166,6 +165,34 @@ impl Config { } } } + + /// Try to get DXVK version applied to wine prefix + /// + /// Returns: + /// 1) `Ok(Some(..))` if version was found + /// 2) `Ok(None)` if version wasn't found, so too old or dxvk is not applied + /// 3) `Err(..)` if failed to get applied dxvk version, likely because wrong prefix path specified + pub fn try_get_selected_dxvk_info(&self) -> std::io::Result> { + let bytes = match std::fs::read(format!("{}/drive_c/windows/system32/dxgi.dll", &self.game.wine.prefix)) { + Ok(bytes) => bytes[1600000..1700000].to_vec(), + Err(_) => std::fs::read(format!("{}/drive_c/windows/system32/d3d11.dll", &self.game.wine.prefix))?[2400000..2500000].to_vec() + }; + + Ok({ + DxvkList::get() + .iter() + .flat_map(|group| group.versions.clone()) + .filter(|version| { + let version = format!("\0v{}\0", &version.version); + let version = version.as_bytes(); + + bytes.windows(version.len()) + .position(|window| window == version) + .is_some() + }) + .next() + }) + } } impl From<&JsonValue> for Config { diff --git a/src/lib/dxvk.rs b/src/lib/dxvk.rs index 18fc1ef..d3f39d7 100644 --- a/src/lib/dxvk.rs +++ b/src/lib/dxvk.rs @@ -62,7 +62,7 @@ pub struct Group { pub versions: Vec } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Version { pub name: String, pub version: String, diff --git a/src/lib/game.rs b/src/lib/game.rs index 55e7ba3..6c521f6 100644 --- a/src/lib/game.rs +++ b/src/lib/game.rs @@ -132,8 +132,8 @@ pub fn run(debug: bool) -> std::io::Result<()> { command.env("WINEPREFIX", &config.game.wine.prefix); // Add DXVK_ASYNC=1 for dxvk-async builds automatically - if let Some(dxvk) = &config.game.dxvk.selected { - if dxvk.contains("async") { + if let Ok(Some(dxvk)) = &config.try_get_selected_dxvk_info() { + if dxvk.version.contains("async") { command.env("DXVK_ASYNC", "1"); } } diff --git a/src/ui/first_run/mod.rs b/src/ui/first_run/mod.rs index be5cd12..78619b8 100644 --- a/src/ui/first_run/mod.rs +++ b/src/ui/first_run/mod.rs @@ -263,6 +263,10 @@ impl App { installer.temp_folder = temp_folder; } + installer.downloader + .set_downloading_speed(config.launcher.speed_limit) + .expect("Failed to set downloading speed limit"); + // Download wine #[allow(unused_must_use)] installer.install(&config.game.wine.builds, move |state| { @@ -317,6 +321,10 @@ impl App { if let Some(temp_folder) = config.launcher.temp { installer.temp_folder = temp_folder; } + + installer.downloader + .set_downloading_speed(config.launcher.speed_limit) + .expect("Failed to set downloading speed limit"); // Download DXVK #[allow(unused_must_use)] @@ -358,7 +366,7 @@ impl App { }, ProgressUpdateResult::Finished => { - let mut config = config::get().unwrap(); + let config = config::get().unwrap(); // Apply DXVK let this = this.clone(); @@ -368,12 +376,7 @@ impl App { match dxvk_version.apply(&config.game.dxvk.builds, &config.game.wine.prefix) { Ok(output) => { println!("Applied DXVK:\n\n{}", String::from_utf8_lossy(&output.stdout)); - - // Update dxvk config - config.game.dxvk.selected = Some(dxvk_version.name.clone()); - - config::update_raw(config.clone()).unwrap(); - + // Remove .first-run file let launcher_dir = crate::lib::consts::launcher_dir().unwrap(); diff --git a/src/ui/main.rs b/src/ui/main.rs index cf07d60..49a6682 100644 --- a/src/ui/main.rs +++ b/src/ui/main.rs @@ -435,6 +435,10 @@ impl App { installer.temp_folder = temp_folder; } + installer.downloader + .set_downloading_speed(config.launcher.speed_limit) + .expect("Failed to set downloading speed limit"); + let (sender, receiver) = glib::MainContext::channel::(glib::PRIORITY_DEFAULT); let this = this.clone(); diff --git a/src/ui/preferences/general.rs b/src/ui/preferences/general.rs index 0a866d8..0b9e7ff 100644 --- a/src/ui/preferences/general.rs +++ b/src/ui/preferences/general.rs @@ -439,16 +439,21 @@ impl App { Actions::UpdateDxvkComboRow => { let model = gtk::StringList::new(&[]); - let list = dxvk::List::list_downloaded(config.game.dxvk.builds) + let list = dxvk::List::list_downloaded(&config.game.dxvk.builds) .expect("Failed to list downloaded DXVK versions"); let mut raw_list = Vec::new(); let mut selected = 0; + let curr = match config.try_get_selected_dxvk_info() { + Ok(Some(curr)) => Some(curr.name), + _ => None + }; + for version in list { model.append(&version.name); - if let Some(curr) = &config.game.dxvk.selected { + if let Some(curr) = &curr { if &version.name == curr { selected = raw_list.len() as u32; } @@ -480,9 +485,16 @@ impl App { if let Some(dxvk_versions) = &values.downloaded_dxvk_versions { let version = dxvk_versions[*i].clone(); + let mut apply = true; - if config.game.dxvk.selected != Some(version.name.clone()) { - config.game.dxvk.selected = Some(version.name.clone()); + if let Ok(Some(curr)) = config.try_get_selected_dxvk_info() { + if version == curr { + apply = false; + } + } + + if apply { + this.widgets.dxvk_selected.set_sensitive(false); std::thread::spawn(clone!(@strong config, @strong this => move || { match version.apply(&config.game.dxvk.builds, &config.game.wine.prefix) { @@ -493,6 +505,8 @@ impl App { )))).unwrap(); } } + + this.widgets.dxvk_selected.set_sensitive(true); })); } } diff --git a/src/ui/traits/download_component.rs b/src/ui/traits/download_component.rs index 2616e2d..79eab12 100644 --- a/src/ui/traits/download_component.rs +++ b/src/ui/traits/download_component.rs @@ -78,13 +78,18 @@ pub trait DownloadComponent { }); let (send, recv) = std::sync::mpsc::channel(); + let config = config::get()?; let mut installer = Installer::new(self.get_download_uri())?; - if let Some(temp_folder) = config::get()?.launcher.temp { + if let Some(temp_folder) = config.launcher.temp { installer.temp_folder = temp_folder; } + installer.downloader + .set_downloading_speed(config.launcher.speed_limit) + .expect("Failed to set downloading speed limit"); + let installation_path = installation_path.to_string(); send.send(installer).unwrap();