From ebebb65e74b1c95c9085a2e2fa88e29f80784f30 Mon Sep 17 00:00:00 2001 From: mkrsym1 Date: Thu, 28 Dec 2023 00:28:46 +0200 Subject: [PATCH] feat: integrated new FPS unlocker --- .../config/schema/game/fps_unlocker/config.rs | 36 +++------- .../{fps_unlocker/mod.rs => fps_unlocker.rs} | 29 ++------ .../genshin/fps_unlocker/config_schema.rs | 69 ------------------- src/games/genshin/game.rs | 14 ++-- 4 files changed, 21 insertions(+), 127 deletions(-) rename src/games/genshin/{fps_unlocker/mod.rs => fps_unlocker.rs} (65%) delete mode 100644 src/games/genshin/fps_unlocker/config_schema.rs diff --git a/src/games/genshin/config/schema/game/fps_unlocker/config.rs b/src/games/genshin/config/schema/game/fps_unlocker/config.rs index 68e0bc1..6216d93 100644 --- a/src/games/genshin/config/schema/game/fps_unlocker/config.rs +++ b/src/games/genshin/config/schema/game/fps_unlocker/config.rs @@ -1,15 +1,11 @@ use serde::{Serialize, Deserialize}; use serde_json::Value as JsonValue; -use crate::config::schema_blanks::prelude::*; - #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub struct Config { pub fps: u64, // TODO: Fps enum - pub power_saving: bool, - pub monitor: u64, - pub window_mode: WindowMode, - pub priority: u64 + pub periodic_writes: bool, + pub interval: u64 } impl Default for Config { @@ -17,10 +13,8 @@ impl Default for Config { fn default() -> Self { Self { fps: 120, - power_saving: false, - monitor: 1, - window_mode: WindowMode::default(), - priority: 3 + periodic_writes: true, + interval: 5000 } } } @@ -35,24 +29,14 @@ impl From<&JsonValue> for Config { None => default.fps }, - power_saving: match value.get("power_saving") { - Some(value) => value.as_bool().unwrap_or(default.power_saving), - None => default.power_saving + periodic_writes: match value.get("periodic_writes") { + Some(value) => value.as_bool().unwrap_or(default.periodic_writes), + None => default.periodic_writes }, - monitor: match value.get("monitor") { - Some(value) => value.as_u64().unwrap_or(default.monitor), - None => default.monitor - }, - - window_mode: match value.get("window_mode") { - Some(value) => WindowMode::from(value), - None => default.window_mode - }, - - priority: match value.get("priority") { - Some(value) => value.as_u64().unwrap_or(default.priority), - None => default.priority + interval: match value.get("interval") { + Some(value) => value.as_u64().unwrap_or(default.interval), + None => default.interval } } } diff --git a/src/games/genshin/fps_unlocker/mod.rs b/src/games/genshin/fps_unlocker.rs similarity index 65% rename from src/games/genshin/fps_unlocker/mod.rs rename to src/games/genshin/fps_unlocker.rs index 9042c87..1cabe7d 100644 --- a/src/games/genshin/fps_unlocker/mod.rs +++ b/src/games/genshin/fps_unlocker.rs @@ -4,13 +4,9 @@ use md5::{Md5, Digest}; use anime_game_core::installer::downloader::Downloader; -use super::config::schema::prelude::FpsUnlockerConfig; - -pub mod config_schema; - const LATEST_INFO: (&str, &str) = ( - "cff81830eebd3566d51b73ffaa444035", - "https://github.com/34736384/genshin-fps-unlock/releases/download/v2.2.0/unlockfps_clr.exe" + "53cb34d292d6b1dd1d8310318fe49bad", + "https://codeberg.org/mkrsym1/fpsunlock/releases/download/v1.0.2/fpsunlock.exe" ); #[derive(Debug, Clone, PartialEq, Eq)] @@ -22,13 +18,13 @@ impl FpsUnlocker { /// Get FpsUnlocker from its containment directory /// /// Returns - /// - `Err(..)` if failed to read `unlocker.exe` file + /// - `Err(..)` if failed to read `fpsunlock.exe` file /// - `Ok(None)` if version is not latest /// - `Ok(..)` if version is latest pub fn from_dir + std::fmt::Debug>(dir: T) -> anyhow::Result> { let dir = dir.into(); - let hash = format!("{:x}", Md5::digest(std::fs::read(dir.join("unlocker.exe"))?)); + let hash = format!("{:x}", Md5::digest(std::fs::read(dir.join("fpsunlock.exe"))?)); Ok(if hash == LATEST_INFO.0 { Some(Self { dir }) @@ -51,7 +47,7 @@ impl FpsUnlocker { std::fs::create_dir_all(&dir)?; } - match downloader.download(dir.join("unlocker.exe"), |_, _| {}) { + match downloader.download(dir.join("fpsunlock.exe"), |_, _| {}) { Ok(_) => Ok(Self { dir }), Err(err) => { tracing::error!("Downloading failed: {err}"); @@ -68,24 +64,11 @@ impl FpsUnlocker { #[inline] pub fn get_binary_in>(dir: T) -> PathBuf { - dir.into().join("unlocker.exe") + dir.into().join("fpsunlock.exe") } #[inline] pub fn dir(&self) -> &PathBuf { &self.dir } - - /// Generate and save FPS unlocker config file to the game's directory - #[tracing::instrument(level = "debug", ret)] - pub fn update_config(&self, config: FpsUnlockerConfig) -> anyhow::Result<()> { - tracing::debug!("Updating FPS unlocker config"); - - let config = config_schema::ConfigSchema::from_config(config); - - Ok(std::fs::write( - self.dir.join("fps_config.json"), - config.json()? - )?) - } } diff --git a/src/games/genshin/fps_unlocker/config_schema.rs b/src/games/genshin/fps_unlocker/config_schema.rs deleted file mode 100644 index 9bb49f0..0000000 --- a/src/games/genshin/fps_unlocker/config_schema.rs +++ /dev/null @@ -1,69 +0,0 @@ -use serde::{Serialize, Deserialize}; - -use crate::config::schema_blanks::prelude::*; -use super::FpsUnlockerConfig; - -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -#[allow(non_snake_case)] -pub struct ConfigSchema { - pub DllList: Vec, - pub Priority: u64, - pub MonitorNum: u64, - pub CustomResY: u64, - pub CustomResX: u64, - pub FPSTarget: u64, - pub UsePowerSave: bool, - pub StartMinimized: bool, - pub IsExclusiveFullscreen: bool, - pub UseCustomRes: bool, - pub Fullscreen: bool, - pub PopupWindow: bool, - pub AutoClose: bool, - pub AutoDisableVSync: bool, - pub AutoStart: bool, - pub GamePath: Option -} - -impl Default for ConfigSchema { - fn default() -> Self { - Self { - DllList: vec![], - Priority: 3, - MonitorNum: 1, - CustomResY: 1080, - CustomResX: 1920, - FPSTarget: 120, - UsePowerSave: false, - IsExclusiveFullscreen: false, - UseCustomRes: false, - Fullscreen: false, - PopupWindow: false, - AutoDisableVSync: true, - GamePath: None, - - // Launcher-specific settings - AutoStart: true, - AutoClose: true, - StartMinimized: true - } - } -} - -impl ConfigSchema { - pub fn from_config(config: FpsUnlockerConfig) -> Self { - Self { - FPSTarget: config.fps, - UsePowerSave: config.power_saving, - PopupWindow: config.window_mode == WindowMode::Popup, - Fullscreen: config.window_mode == WindowMode::Fullscreen, - MonitorNum: config.monitor, - Priority: config.priority, - - ..Self::default() - } - } - - pub fn json(&self) -> serde_json::Result { - serde_json::to_string(self) - } -} diff --git a/src/games/genshin/game.rs b/src/games/genshin/game.rs index 0a42efc..ec9e747 100644 --- a/src/games/genshin/game.rs +++ b/src/games/genshin/game.rs @@ -89,8 +89,7 @@ pub fn run() -> anyhow::Result<()> { // Prepare fps unlocker // 1) Download if needed - // 2) Generate config file - // 3) Generate fpsunlocker.bat from launcher.bat + // 2) Generate fps_unlocker.bat #[cfg(feature = "fps-unlocker")] if config.game.enhancements.fps_unlocker.enabled { @@ -115,14 +114,11 @@ pub fn run() -> anyhow::Result<()> { } }; - // Generate FPS unlocker config file - if let Err(err) = unlocker.update_config(config.game.enhancements.fps_unlocker.config) { - return Err(anyhow::anyhow!("Failed to update FPS unlocker config: {err}")); - } - // If patch applying is disabled, then game_executable is either GenshinImpact.exe or YuanShen.exe // so we don't need to check it here - std::fs::write(game_path.join("fps_unlocker.bat"), format!("start {game_executable} %*\n\nZ:\ncd \"{}\"\nstart unlocker.exe", unlocker.dir().to_string_lossy()))?; + let unlocker_config = &config.game.enhancements.fps_unlocker.config; + let unlocker_interval = if unlocker_config.periodic_writes { unlocker_config.interval as i64 } else { -1 }; + std::fs::write(game_path.join("fps_unlocker.bat"), format!("start {game_executable} %*\n\nZ:\ncd \"{}\"\nstart fpsunlock.exe {} {unlocker_interval}", unlocker.dir().to_string_lossy(), unlocker_config.fps))?; } // Generate `config.ini` if environment emulation feature is presented @@ -314,7 +310,7 @@ pub fn run() -> anyhow::Result<()> { let output = Command::new("ps").arg("-A").stdout(Stdio::piped()).output()?; let output = String::from_utf8_lossy(&output.stdout); - if !output.contains("GenshinImpact.e") && !output.contains("YuanShen.exe") && !output.contains("unlocker.exe") { + if !output.contains("GenshinImpact.e") && !output.contains("YuanShen.exe") && !output.contains("fpsunlock.exe") { break; }