mirror of
https://github.com/an-anime-team/sleepy-launcher.git
synced 2025-03-15 06:28:27 +03:00
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:
parent
3d1674975d
commit
ddc122d631
7 changed files with 154 additions and 128 deletions
30
Cargo.lock
generated
30
Cargo.lock
generated
|
@ -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
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
182
src/ui/main.rs
182
src/ui/main.rs
|
@ -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));
|
||||
|
|
|
@ -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 = >k::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)]
|
||||
|
|
|
@ -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)]
|
||||
|
|
Loading…
Add table
Reference in a new issue