feat(core): implemented SDK 0.5.12

This change allows to support game edition switching in settings
This commit is contained in:
Observer KRypt0n_ 2023-04-08 19:46:28 +02:00
parent 941851c234
commit deacef3759
No known key found for this signature in database
GPG key ID: 844DA47BA25FE1E2
9 changed files with 118 additions and 41 deletions

4
Cargo.lock generated
View file

@ -86,8 +86,8 @@ dependencies = [
[[package]]
name = "anime-launcher-sdk"
version = "0.5.11"
source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=0.5.11#46547a886f51ba8c58918c0903273c3d3c63d5fa"
version = "0.5.12"
source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=0.5.12#06f0f486b9e099fc96db71be339332e1961dd0f6"
dependencies = [
"anime-game-core",
"anyhow",

View file

@ -17,7 +17,7 @@ glib-build-tools = "0.17"
[dependencies.anime-launcher-sdk]
git = "https://github.com/an-anime-team/anime-launcher-sdk"
tag = "0.5.11"
tag = "0.5.12"
# path = "../anime-launcher-sdk" # ! for dev purposes only

View file

@ -37,7 +37,7 @@ lazy_static::lazy_static! {
/// This one is used to prepare some launcher UI components on start
pub static ref CONFIG: config::Config = config::get().expect("Failed to load config");
pub static ref GAME: Game = Game::new(&CONFIG.game.path);
pub static ref GAME: Game = Game::new(CONFIG.game.path.for_edition(CONFIG.launcher.edition));
/// Path to launcher folder. Standard is `$HOME/.local/share/anime-game-launcher`
pub static ref LAUNCHER_FOLDER: PathBuf = launcher_dir().expect("Failed to get launcher folder");

View file

@ -18,7 +18,8 @@ pub struct DefaultPathsApp {
runners: PathBuf,
dxvks: PathBuf,
prefix: PathBuf,
game: PathBuf,
game_global: PathBuf,
game_china: PathBuf,
fps_unlocker: PathBuf,
components: PathBuf,
patch: PathBuf,
@ -31,7 +32,8 @@ pub enum Folders {
Runners,
DXVK,
Prefix,
Game,
GameGlobal,
GameChina,
FpsUnlocker,
Components,
Patch,
@ -144,9 +146,20 @@ impl SimpleAsyncComponent for DefaultPathsApp {
set_activatable: true,
#[watch]
set_subtitle: model.game.to_str().unwrap(),
set_subtitle: model.game_global.to_str().unwrap(),
connect_activated => DefaultPathsAppMsg::ChoosePath(Folders::Game)
connect_activated => DefaultPathsAppMsg::ChoosePath(Folders::GameGlobal)
},
adw::ActionRow {
set_title: &tr("game-installation-folder"), // FIXME
set_icon_name: Some("folder-symbolic"),
set_activatable: true,
#[watch]
set_subtitle: model.game_china.to_str().unwrap(),
connect_activated => DefaultPathsAppMsg::ChoosePath(Folders::GameChina)
},
adw::ActionRow {
@ -233,7 +246,8 @@ impl SimpleAsyncComponent for DefaultPathsApp {
runners: CONFIG.game.wine.builds.clone(),
dxvks: CONFIG.game.dxvk.builds.clone(),
prefix: CONFIG.game.wine.prefix.clone(),
game: CONFIG.game.path.clone(),
game_global: CONFIG.game.path.global.clone(),
game_china: CONFIG.game.path.china.clone(),
fps_unlocker: CONFIG.game.enhancements.fps_unlocker.path.clone(),
components: CONFIG.components.path.clone(),
patch: CONFIG.patch.path.clone(),
@ -264,23 +278,21 @@ impl SimpleAsyncComponent for DefaultPathsApp {
self.runners = result.join("runners");
self.dxvks = result.join("dxvks");
self.prefix = result.join("prefix");
self.game_global = result.join(concat!("Ge", "nshi", "n Imp", "act"));
self.game_china = result.join(concat!("Yu", "anS", "hen"));
self.fps_unlocker = result.join("fps-unlocker");
self.components = result.join("components");
self.patch = result.join("patch");
self.temp = result.clone();
self.game = result.join(match CONFIG.launcher.edition.into() {
GameEdition::Global => concat!("Ge", "nshi", "n Imp", "act"),
GameEdition::China => concat!("Yu", "anS", "hen")
});
self.launcher = result;
}
Folders::Runners => self.runners = result,
Folders::DXVK => self.dxvks = result,
Folders::Prefix => self.prefix = result,
Folders::Game => self.game = result,
Folders::GameGlobal => self.game_global = result,
Folders::GameChina => self.game_china = result,
Folders::FpsUnlocker => self.fps_unlocker = result,
Folders::Components => self.components = result,
Folders::Patch => self.patch = result,
@ -313,7 +325,8 @@ impl DefaultPathsApp {
config.game.wine.builds = self.runners.clone();
config.game.dxvk.builds = self.dxvks.clone();
config.game.wine.prefix = self.prefix.clone();
config.game.path = self.game.clone();
config.game.path.global = self.game_global.clone();
config.game.path.china = self.game_china.clone();
config.components.path = self.components.clone();
config.patch.path = self.patch.clone();
config.launcher.temp = Some(self.temp.clone());

View file

@ -21,7 +21,7 @@ pub fn apply_patch<T: PatchExt + Send + Sync + 'static>(sender: ComponentSender<
std::thread::spawn(move || {
let mut apply_patch_if_needed = true;
if let Err(err) = patch.apply(&config.game.path, config.patch.root) {
if let Err(err) = patch.apply(config.game.path.for_edition(config.launcher.edition), config.patch.root) {
tracing::error!("Failed to patch the game");
sender.input(AppMsg::Toast {

View file

@ -18,9 +18,10 @@ pub fn download_diff(sender: ComponentSender<App>, progress_bar_input: Sender<Pr
std::thread::spawn(move || {
let config = config::get().unwrap();
let game_path = config.game.path.for_edition(config.launcher.edition).to_path_buf();
#[allow(unused_must_use)]
let result = diff.install_to_by(config.game.path, config.launcher.temp, clone!(@strong sender => move |state| {
let result = diff.install_to_by(game_path, config.launcher.temp, clone!(@strong sender => move |state| {
match &state {
InstallerUpdate::DownloadingError(err) => {
tracing::error!("Downloading failed: {err}");

View file

@ -554,7 +554,12 @@ impl SimpleComponent for App {
})));
group.add_action::<GameFolder>(&RelmAction::new_stateless(clone!(@strong sender => move |_| {
if let Err(err) = open::that(&CONFIG.game.path) {
let path = match config::get() {
Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(),
Err(_) => CONFIG.game.path.for_edition(CONFIG.launcher.edition).to_path_buf(),
};
if let Err(err) = open::that(path) {
sender.input(AppMsg::Toast {
title: tr("game-folder-opening-error"),
description: Some(err.to_string())
@ -590,8 +595,10 @@ impl SimpleComponent for App {
group.add_action::<WishUrl>(&RelmAction::new_stateless(clone!(@strong sender => move |_| {
std::thread::spawn(clone!(@strong sender => move || {
let web_cache = CONFIG.game.path
.join(GameEdition::selected().data_folder())
let config = config::get().unwrap_or_else(|_| CONFIG.clone());
let web_cache = config.game.path.for_edition(config.launcher.edition)
.join(GameEdition::from(config.launcher.edition).data_folder())
.join("webCaches/Cache/Cache_Data/data_2");
if !web_cache.exists() {

View file

@ -3,6 +3,8 @@ use relm4::{
Sender
};
use gtk::glib::clone;
use std::path::Path;
use anime_launcher_sdk::config;
@ -23,7 +25,8 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
match repairer::try_get_integrity_files(None) {
Ok(mut files) => {
// Add voiceovers files
let game = Game::new(&config.game.path);
let game_path = config.game.path.for_edition(config.launcher.edition).to_path_buf();
let game = Game::new(&game_path);
if let Ok(voiceovers) = game.get_voice_packages() {
for package in voiceovers {
@ -61,10 +64,9 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
}
}
let game_path = config.game.path.clone();
let thread_sender = verify_sender.clone();
std::thread::spawn(move || {
std::thread::spawn(clone!(@strong game_path => move || {
for file in thread_files {
let status = if config.launcher.repairer.fast {
file.fast_verify(&game_path)
@ -74,7 +76,7 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
thread_sender.send((file, status)).unwrap();
}
});
}));
}
// We have [config.launcher.repairer.threads] copies of this sender + the original one
@ -105,10 +107,10 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
let total = broken.len() as f64;
let player_patch = UnityPlayerPatch::from_folder(&config.patch.path).unwrap()
.is_applied(&config.game.path).unwrap();
.is_applied(&game_path).unwrap();
let xlua_patch = UnityPlayerPatch::from_folder(&config.patch.path).unwrap()
.is_applied(&config.game.path).unwrap();
let xlua_patch = XluaPatch::from_folder(&config.patch.path).unwrap()
.is_applied(&game_path).unwrap();
tracing::debug!("Patches status: player({player_patch}), xlua({xlua_patch})");
@ -145,7 +147,7 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
if !should_ignore(&file.path, player_patch, xlua_patch) {
tracing::debug!("Repairing file: {}", file.path.to_string_lossy());
if let Err(err) = file.repair(&config.game.path) {
if let Err(err) = file.repair(&game_path) {
sender.input(AppMsg::Toast {
title: tr("game-file-repairing-error"),
description: Some(err.to_string())

View file

@ -16,6 +16,7 @@ use anime_launcher_sdk::config::launcher::LauncherStyle;
use anime_launcher_sdk::components::*;
use anime_launcher_sdk::components::wine::WincompatlibWine;
use anime_launcher_sdk::env_emulation::Environment;
use anime_launcher_sdk::config::launcher::GameEdition;
use super::main::PreferencesAppMsg;
use crate::ui::migrate_installation::MigrateInstallationApp;
@ -301,15 +302,41 @@ impl SimpleAsyncComponent for GeneralApp {
}
},
#[local_ref]
voice_packages -> adw::ExpanderRow {
set_title: &tr("game-voiceovers"),
set_subtitle: "List of downloaded game voiceovers. You can select them in the game settings"
adw::ComboRow {
set_title: "Game edition",
set_model: Some(&gtk::StringList::new(&[
"Global",
"China"
])),
set_selected: match CONFIG.launcher.edition {
GameEdition::Global => 0,
GameEdition::China => 1
},
connect_selected_notify[sender] => move |row| {
if is_ready() {
#[allow(unused_must_use)]
if let Ok(mut config) = config::get() {
config.launcher.edition = match row.selected() {
0 => GameEdition::Global,
1 => GameEdition::China,
_ => unreachable!()
};
config::update(config);
sender.output(PreferencesAppMsg::UpdateLauncherState);
}
}
}
},
adw::ComboRow {
set_title: "Environment emulation",
set_subtitle: "Experimental feature. Emulate game environment to get specific features like additional payment methods",
set_title: "Game environment",
set_subtitle: "Get specific features like additional payment methods",
set_model: Some(&gtk::StringList::new(&[
"PC",
@ -339,6 +366,12 @@ impl SimpleAsyncComponent for GeneralApp {
}
},
#[local_ref]
voice_packages -> adw::ExpanderRow {
set_title: &tr("game-voiceovers"),
set_subtitle: "List of downloaded game voiceovers. You can select them in the game settings"
},
gtk::Box {
set_orientation: gtk::Orientation::Horizontal,
set_spacing: 8,
@ -442,7 +475,12 @@ impl SimpleAsyncComponent for GeneralApp {
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) {
let path = match config::get() {
Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(),
Err(_) => CONFIG.game.path.for_edition(CONFIG.launcher.edition).to_path_buf(),
};
if let Ok(true) = model.unity_player_patch.as_ref().unwrap_unchecked().is_applied(path) {
&["success"]
} else {
&["warning"]
@ -464,7 +502,12 @@ impl SimpleAsyncComponent for GeneralApp {
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) {
let path = match config::get() {
Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(),
Err(_) => CONFIG.game.path.for_edition(CONFIG.launcher.edition).to_path_buf(),
};
if let Ok(true) = model.unity_player_patch.as_ref().unwrap_unchecked().is_applied(path) {
String::new()
} else {
tr("patch-not-applied-tooltip")
@ -503,7 +546,12 @@ impl SimpleAsyncComponent for GeneralApp {
PatchStatus::Preparation { .. } |
PatchStatus::Testing { .. } => &["warning"],
PatchStatus::Available { .. } => unsafe {
if let Ok(true) = model.xlua_patch.as_ref().unwrap_unchecked().is_applied(&CONFIG.game.path) {
let path = match config::get() {
Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(),
Err(_) => CONFIG.game.path.for_edition(CONFIG.launcher.edition).to_path_buf(),
};
if let Ok(true) = model.xlua_patch.as_ref().unwrap_unchecked().is_applied(path) {
&["success"]
} else {
&["warning"]
@ -525,7 +573,12 @@ impl SimpleAsyncComponent for GeneralApp {
PatchStatus::Preparation { .. } => tr("patch-preparation-tooltip"),
PatchStatus::Testing { .. } => tr("patch-testing-tooltip"),
PatchStatus::Available { .. } => unsafe {
if let Ok(true) = model.xlua_patch.as_ref().unwrap_unchecked().is_applied(&CONFIG.game.path) {
let path = match config::get() {
Ok(config) => config.game.path.for_edition(config.launcher.edition).to_path_buf(),
Err(_) => CONFIG.game.path.for_edition(CONFIG.launcher.edition).to_path_buf(),
};
if let Ok(true) = model.xlua_patch.as_ref().unwrap_unchecked().is_applied(path) {
String::new()
} else {
tr("patch-not-applied-tooltip")
@ -867,10 +920,11 @@ impl SimpleAsyncComponent for GeneralApp {
config::update(config.clone());
let package = VoicePackage::with_locale(package.locale).unwrap();
let game_path = config.game.path.for_edition(config.launcher.edition).to_path_buf();
if package.is_installed_in(&config.game.path) {
if package.is_installed_in(&game_path) {
std::thread::spawn(move || {
if let Err(err) = package.delete_in(&config.game.path) {
if let Err(err) = package.delete_in(game_path) {
tracing::error!("Failed to delete voice package: {:?}", package.locale());
sender.input(GeneralAppMsg::Toast {