feat(core): implemented core library 1.4.0

It now allowed to use several patches for the game. As well it now uses `GitRemoteSync`
trait like components index does with gains more stability I guess
This commit is contained in:
Observer KRypt0n_ 2023-03-22 17:25:26 +02:00
parent 3d1674975d
commit ddc122d631
No known key found for this signature in database
GPG key ID: 844DA47BA25FE1E2
7 changed files with 154 additions and 128 deletions

30
Cargo.lock generated
View file

@ -31,7 +31,7 @@ dependencies = [
[[package]]
name = "anime-game-core"
version = "1.3.12"
version = "1.4.0"
dependencies = [
"anyhow",
"bzip2",
@ -76,12 +76,12 @@ dependencies = [
[[package]]
name = "anime-launcher-sdk"
version = "0.5.3"
version = "0.5.4"
dependencies = [
"anime-game-core",
"anyhow",
"cached",
"dirs",
"dirs 5.0.0",
"discord-rich-presence",
"enum-ordinalize",
"lazy_static",
@ -581,7 +581,16 @@ version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
dependencies = [
"dirs-sys",
"dirs-sys 0.3.7",
]
[[package]]
name = "dirs"
version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dece029acd3353e3a58ac2e3eb3c8d6c35827a892edc6cc4138ef9c33df46ecd"
dependencies = [
"dirs-sys 0.4.0",
]
[[package]]
@ -595,6 +604,17 @@ dependencies = [
"winapi",
]
[[package]]
name = "dirs-sys"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04414300db88f70d74c5ff54e50f9e1d1737d9a5b90f53fcf2e95ca2a9ab554b"
dependencies = [
"libc",
"redox_users",
"windows-sys 0.45.0",
]
[[package]]
name = "discord-rich-presence"
version = "0.2.3"
@ -3053,7 +3073,7 @@ dependencies = [
"async-trait",
"byteorder",
"derivative",
"dirs",
"dirs 4.0.0",
"enumflags2",
"event-listener",
"futures-core",

@ -1 +1 @@
Subproject commit f244a20b42dd1cf43ae7955d2a26c0b33b2ccdbe
Subproject commit 78bb7082472d882d68574dd05ce3c392ab7c387a

View file

@ -191,7 +191,7 @@ fn main() {
}
LauncherState::PredownloadAvailable { .. } |
LauncherState::PatchAvailable(Patch::NotAvailable) => {
LauncherState::MainPatchAvailable(UnityPlayerPatch { status: PatchStatus::NotAvailable, .. }) => {
if just_run_game {
anime_launcher_sdk::game::run().expect("Failed to run the game");

View file

@ -227,9 +227,9 @@ impl SimpleComponent for FirstRunApp {
#[allow(unused_must_use)]
std::thread::spawn(move || {
match components.is_sync(config.components.servers) {
Ok(true) => (),
Ok(Some(_)) => (),
Ok(false) => {
Ok(None) => {
for host in &CONFIG.components.servers {
match components.sync(host) {
Ok(true) => break,

View file

@ -68,7 +68,9 @@ pub enum AppMsg {
/// Supposed to be called automatically on app's run when the latest patch version
/// was retrieved from remote repos
SetPatch(Option<Patch>),
SetUnityPlayerPatch(Option<UnityPlayerPatch>),
// TODO: xlua patch status
/// Supposed to be called automatically on app's run when the launcher state was chosen
SetLauncherState(Option<LauncherState>),
@ -357,7 +359,7 @@ impl SimpleComponent for App {
set_label: &match model.state {
Some(LauncherState::Launch) => tr("launch"),
Some(LauncherState::PredownloadAvailable { .. }) => tr("launch"),
Some(LauncherState::PatchAvailable(_)) => tr("apply-patch"),
Some(LauncherState::MainPatchAvailable(_)) => tr("apply-patch"),
Some(LauncherState::WineNotInstalled) => tr("download-wine"),
Some(LauncherState::PrefixNotExists) => tr("create-prefix"),
Some(LauncherState::VoiceUpdateAvailable(_)) => tr("update"),
@ -375,13 +377,13 @@ impl SimpleComponent for App {
Some(LauncherState::GameOutdated { .. }) |
Some(LauncherState::VoiceOutdated(_)) => false,
Some(LauncherState::PatchAvailable(patch)) => match patch {
Patch::NotAvailable |
Patch::Outdated { .. } |
Patch::Preparation { .. } => false,
Some(LauncherState::MainPatchAvailable(UnityPlayerPatch { status, .. })) => match status {
PatchStatus::NotAvailable |
PatchStatus::Outdated { .. } |
PatchStatus::Preparation { .. } => false,
Patch::Testing { .. } |
Patch::Available { .. } => true
PatchStatus::Testing { .. } |
PatchStatus::Available { .. } => true
},
Some(_) => true,
@ -394,13 +396,13 @@ impl SimpleComponent for App {
Some(LauncherState::GameOutdated { .. }) |
Some(LauncherState::VoiceOutdated(_)) => &["warning"],
Some(LauncherState::PatchAvailable(patch)) => match patch {
Patch::NotAvailable |
Patch::Outdated { .. } |
Patch::Preparation { .. } => &["error"],
Some(LauncherState::MainPatchAvailable(UnityPlayerPatch { status, .. })) => match status {
PatchStatus::NotAvailable |
PatchStatus::Outdated { .. } |
PatchStatus::Preparation { .. } => &["error"],
Patch::Testing { .. } => &["warning"],
Patch::Available { .. } => &["suggested-action"]
PatchStatus::Testing { .. } => &["warning"],
PatchStatus::Available { .. } => &["suggested-action"]
},
Some(_) => &["suggested-action"],
@ -413,11 +415,11 @@ impl SimpleComponent for App {
Some(LauncherState::GameOutdated { .. }) |
Some(LauncherState::VoiceOutdated(_)) => tr("main-window--version-outdated-tooltip"),
Some(LauncherState::PatchAvailable(patch)) => match patch {
Patch::NotAvailable => tr("main-window--patch-unavailable-tooltip"),
Some(LauncherState::MainPatchAvailable(UnityPlayerPatch { status, .. })) => match status {
PatchStatus::NotAvailable => tr("main-window--patch-unavailable-tooltip"),
Patch::Outdated { .. } |
Patch::Preparation { .. } => tr("main-window--patch-outdated-tooltip"),
PatchStatus::Outdated { .. } |
PatchStatus::Preparation { .. } => tr("main-window--patch-outdated-tooltip"),
_ => String::new()
},
@ -607,9 +609,9 @@ impl SimpleComponent for App {
let components = ComponentsLoader::new(&CONFIG.components.path);
match components.is_sync(&CONFIG.components.servers) {
Ok(true) => (),
Ok(Some(_)) => (),
Ok(false) => {
Ok(None) => {
for host in &CONFIG.components.servers {
match components.sync(host) {
Ok(true) => {
@ -669,10 +671,54 @@ impl SimpleComponent for App {
sender.input(AppMsg::SetLoadingStatus(Some(Some(tr("loading-patch-status")))));
sender.input(AppMsg::SetPatch(match Patch::try_fetch(&CONFIG.patch.servers, None) {
Ok(patch) => Some(patch),
// Sync local patch repo
let patch = Patch::new(&CONFIG.patch.path);
match patch.is_sync(&CONFIG.patch.servers) {
Ok(Some(_)) => (),
Ok(None) => {
for server in &CONFIG.patch.servers {
match patch.sync(server) {
Ok(true) => break,
Ok(false) => {
tracing::error!("Failed to sync patch folder with remote: {server}");
sender.input(AppMsg::Toast {
title: tr("patch-sync-failed"),
description: None
});
}
Err(err) => {
tracing::error!("Failed to sync patch folder with remote: {server}: {err}");
sender.input(AppMsg::Toast {
title: tr("patch-sync-failed"),
description: Some(err.to_string())
});
}
}
}
}
Err(err) => {
tracing::error!("Failed to fetch patch info: {err}");
tracing::error!("Failed to compare local patch folder with remote: {err}");
sender.input(AppMsg::Toast {
title: tr("patch-state-check-failed"),
description: Some(err.to_string())
});
}
}
// Get main patch status
let main_patch = match patch.unity_player_patch() {
Ok(patch) => Some(patch),
Err(err) => {
tracing::error!("Failed to fetch unity player patch info: {err}");
sender.input(AppMsg::Toast {
title: tr("patch-info-fetching-error"),
@ -681,7 +727,9 @@ impl SimpleComponent for App {
None
}
}));
};
sender.input(AppMsg::SetUnityPlayerPatch(main_patch));
tracing::info!("Updated patch status");
@ -777,8 +825,8 @@ impl SimpleComponent for App {
}
#[allow(unused_must_use)]
AppMsg::SetPatch(patch) => unsafe {
PREFERENCES_WINDOW.as_ref().unwrap_unchecked().sender().send(PreferencesAppMsg::SetPatch(patch));
AppMsg::SetUnityPlayerPatch(patch) => unsafe {
PREFERENCES_WINDOW.as_ref().unwrap_unchecked().sender().send(PreferencesAppMsg::SetUnityPlayerPatch(patch));
}
AppMsg::SetLauncherState(state) => {
@ -900,10 +948,9 @@ impl SimpleComponent for App {
let total = broken.len() as f64;
let is_patch_applied = match Patch::try_fetch(config.patch.servers, anime_launcher_sdk::consts::PATCH_FETCHING_TIMEOUT) {
Ok(patch) => patch.is_applied(&config.game.path).unwrap_or(true),
Err(_) => true
};
// TODO: properly handle xlua patch
let is_patch_applied = UnityPlayerPatch::from_folder(&config.patch.path).unwrap()
.is_applied(&config.game.path).unwrap();
tracing::debug!("Patch status: {}", is_patch_applied);
@ -994,9 +1041,9 @@ impl SimpleComponent for App {
AppMsg::PerformAction => unsafe {
match self.state.as_ref().unwrap_unchecked() {
LauncherState::PatchAvailable(Patch::NotAvailable) |
LauncherState::MainPatchAvailable(UnityPlayerPatch { status: PatchStatus::NotAvailable, .. }) |
LauncherState::PredownloadAvailable { .. } |
LauncherState::Launch => {
LauncherState::Launch => {
sender.input(AppMsg::HideWindow);
std::thread::spawn(move || {
@ -1013,69 +1060,28 @@ impl SimpleComponent for App {
});
}
LauncherState::PatchAvailable(patch) => {
match patch.to_owned() {
Patch::NotAvailable |
Patch::Outdated { .. } |
Patch::Preparation { .. } => unreachable!(),
LauncherState::MainPatchAvailable(patch) => {
let patch = patch.to_owned();
Patch::Testing { version, host, .. } |
Patch::Available { version, host, .. } => {
match patch.status() {
PatchStatus::NotAvailable |
PatchStatus::Outdated { .. } |
PatchStatus::Preparation { .. } => unreachable!(),
PatchStatus::Testing { .. } |
PatchStatus::Available { .. } => {
self.disabled_buttons = true;
let config = config::get().unwrap();
std::thread::spawn(move || {
let applier = PatchApplier::new(&config.patch.path);
if let Err(err) = patch.apply(&config.game.path, config.patch.root) {
tracing::error!("Failed to patch the game");
let mut synced = false;
match applier.is_sync_with(&host) {
Ok(true) => synced = true,
Ok(false) => {
match applier.sync(&host) {
Ok(true) => synced = true,
Ok(false) => {
tracing::error!("Failed to sync patch folder with remote: {host}");
sender.input(AppMsg::Toast {
title: tr("patch-sync-failed"),
description: None
});
}
Err(err) => {
tracing::error!("Failed to sync patch folder with remote: {host}: {err}");
sender.input(AppMsg::Toast {
title: tr("patch-sync-failed"),
description: Some(err.to_string())
});
}
}
}
Err(err) => {
tracing::error!("Failed to compare local patch folder with remote: {host}");
sender.input(AppMsg::Toast {
title: tr("patch-state-check-failed"),
description: Some(err.to_string())
});
}
}
if synced {
if let Err(err) = applier.apply(&config.game.path, version, config.patch.root) {
tracing::error!("Failed to patch the game using remote: {host}");
sender.input(AppMsg::Toast {
title: tr("game-patching-error"),
description: Some(err.to_string())
});
}
sender.input(AppMsg::Toast {
title: tr("game-patching-error"),
description: Some(err.to_string())
});
}
sender.input(AppMsg::DisableButtons(false));

View file

@ -106,7 +106,7 @@ pub struct GeneralApp {
dxvk_components: AsyncController<ComponentsList<GeneralAppMsg>>,
game_diff: Option<VersionDiff>,
patch: Option<Patch>,
unity_player_patch: Option<UnityPlayerPatch>,
style: LauncherStyle,
@ -131,7 +131,7 @@ pub enum GeneralAppMsg {
/// Supposed to be called automatically on app's run when the latest patch version
/// was retrieved from remote repos
SetPatch(Option<Patch>),
SetUnityPlayerPatch(Option<UnityPlayerPatch>),
// If one ever wich to change it to accept VoiceLocale
// I'd recommend to use clone!(@strong self.locale as locale => move |_| { .. })
@ -372,27 +372,27 @@ impl SimpleAsyncComponent for GeneralApp {
add_suffix = &gtk::Label {
#[watch]
set_text: &match model.patch.as_ref() {
Some(patch) => match patch {
Patch::NotAvailable => tr("patch-not-available"),
Patch::Outdated { current, .. } => tr_args("patch-outdated", [("current", current.to_string().into())]),
Patch::Preparation { .. } => tr("patch-preparation"),
Patch::Testing { version, .. } |
Patch::Available { version, .. } => version.to_string()
set_text: &match model.unity_player_patch.as_ref() {
Some(patch) => match patch.status() {
PatchStatus::NotAvailable => tr("patch-not-available"),
PatchStatus::Outdated { current, .. } => tr_args("patch-outdated", [("current", current.to_string().into())]),
PatchStatus::Preparation { .. } => tr("patch-preparation"),
PatchStatus::Testing { version, .. } |
PatchStatus::Available { version, .. } => version.to_string()
}
None => String::from("?")
},
#[watch]
set_css_classes: match model.patch.as_ref() {
Some(patch) => match patch {
Patch::NotAvailable => &["error"],
Patch::Outdated { .. } |
Patch::Preparation { .. } |
Patch::Testing { .. } => &["warning"],
Patch::Available { .. } => unsafe {
if let Ok(true) = model.patch.as_ref().unwrap_unchecked().is_applied(&CONFIG.game.path) {
set_css_classes: match model.unity_player_patch.as_ref() {
Some(patch) => match patch.status() {
PatchStatus::NotAvailable => &["error"],
PatchStatus::Outdated { .. } |
PatchStatus::Preparation { .. } |
PatchStatus::Testing { .. } => &["warning"],
PatchStatus::Available { .. } => unsafe {
if let Ok(true) = model.unity_player_patch.as_ref().unwrap_unchecked().is_applied(&CONFIG.game.path) {
&["success"]
} else {
&["warning"]
@ -404,17 +404,17 @@ impl SimpleAsyncComponent for GeneralApp {
},
#[watch]
set_tooltip_text: Some(&match model.patch.as_ref() {
Some(patch) => match patch {
Patch::NotAvailable => tr("patch-not-available-tooltip"),
Patch::Outdated { current, latest, .. } => tr_args("patch-outdated-tooltip", [
set_tooltip_text: Some(&match model.unity_player_patch.as_ref() {
Some(patch) => match patch.status() {
PatchStatus::NotAvailable => tr("patch-not-available-tooltip"),
PatchStatus::Outdated { current, latest, .. } => tr_args("patch-outdated-tooltip", [
("current", current.to_string().into()),
("latest", latest.to_string().into())
]),
Patch::Preparation { .. } => tr("patch-preparation-tooltip"),
Patch::Testing { .. } => tr("patch-testing-tooltip"),
Patch::Available { .. } => unsafe {
if let Ok(true) = model.patch.as_ref().unwrap_unchecked().is_applied(&CONFIG.game.path) {
PatchStatus::Preparation { .. } => tr("patch-preparation-tooltip"),
PatchStatus::Testing { .. } => tr("patch-testing-tooltip"),
PatchStatus::Available { .. } => unsafe {
if let Ok(true) = model.unity_player_patch.as_ref().unwrap_unchecked().is_applied(&CONFIG.game.path) {
String::new()
} else {
tr("patch-testing-tooltip")
@ -614,7 +614,7 @@ impl SimpleAsyncComponent for GeneralApp {
.forward(sender.input_sender(), std::convert::identity),
game_diff: None,
patch: None,
unity_player_patch: None,
style: CONFIG.launcher.style,
@ -661,8 +661,8 @@ impl SimpleAsyncComponent for GeneralApp {
self.game_diff = diff;
}
GeneralAppMsg::SetPatch(patch) => {
self.patch = patch;
GeneralAppMsg::SetUnityPlayerPatch(patch) => {
self.unity_player_patch = patch;
}
#[allow(unused_must_use)]

View file

@ -30,7 +30,7 @@ pub enum PreferencesAppMsg {
/// Supposed to be called automatically on app's run when the latest patch version
/// was retrieved from remote repos
SetPatch(Option<Patch>),
SetUnityPlayerPatch(Option<UnityPlayerPatch>),
SetLauncherStyle(LauncherStyle),
@ -125,8 +125,8 @@ impl SimpleAsyncComponent for PreferencesApp {
}
#[allow(unused_must_use)]
PreferencesAppMsg::SetPatch(patch) => {
self.general.sender().send(GeneralAppMsg::SetPatch(patch));
PreferencesAppMsg::SetUnityPlayerPatch(patch) => {
self.general.sender().send(GeneralAppMsg::SetUnityPlayerPatch(patch));
}
#[allow(unused_must_use)]