mirror of
https://github.com/an-anime-team/an-anime-game-launcher.git
synced 2025-03-11 02:29:37 +03:00
feat(core): implemented SDK 0.5.12
This change allows to support game edition switching in settings
This commit is contained in:
parent
941851c234
commit
deacef3759
9 changed files with 118 additions and 41 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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}");
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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(>k::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(>k::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 {
|
||||
|
|
Loading…
Add table
Reference in a new issue