feat(star-rail): integrated jadeite patch

This commit is contained in:
Observer KRypt0n_ 2023-06-10 22:08:06 +02:00
parent 60d800a23d
commit 947b243245
No known key found for this signature in database
GPG key ID: 844DA47BA25FE1E2
4 changed files with 53 additions and 73 deletions

View file

@ -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"]

View file

@ -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<String>,
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
}
}
}

View file

@ -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}");

View file

@ -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<F: Fn(StateUpdating)> {
pub game_edition: GameEdition,
pub wine_prefix: PathBuf,
pub patch_servers: Vec<String>,
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(&params.patch_folder, params.game_edition);
if !jadeite::is_installed(&params.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(&params.patch_servers)?.is_none() {
for server in &params.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(&params.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