feat(core): initial multi-edition support

This commit is contained in:
Observer KRypt0n_ 2023-04-23 10:11:11 +02:00
parent 81e7b9c5a7
commit 6c442bd947
No known key found for this signature in database
GPG key ID: 844DA47BA25FE1E2
7 changed files with 57 additions and 34 deletions

View file

@ -40,7 +40,7 @@ lazy_static::lazy_static! {
/// This one is used to prepare some launcher UI components on start
pub static ref CONFIG: Schema = 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

@ -21,7 +21,8 @@ pub struct DefaultPathsApp {
runners: PathBuf,
dxvks: PathBuf,
prefix: PathBuf,
game: PathBuf,
game_global: PathBuf,
game_china: PathBuf,
components: PathBuf,
patch: PathBuf,
temp: PathBuf
@ -33,7 +34,8 @@ pub enum Folders {
Runners,
DXVK,
Prefix,
Game,
GameGlobal,
GameChina,
Components,
Patch,
Temp
@ -147,14 +149,25 @@ impl SimpleAsyncComponent for DefaultPathsApp {
},
adw::ActionRow {
set_title: &tr("global-game-installation-folder"), // FIXME: locale
set_title: &tr("global-game-installation-folder"),
set_icon_name: Some("folder-symbolic"),
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("chinese-game-installation-folder"),
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 {
@ -272,7 +285,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(),
components: CONFIG.components.path.clone(),
patch: CONFIG.patch.path.clone(),
@ -302,24 +316,26 @@ impl SimpleAsyncComponent for DefaultPathsApp {
match folder {
Folders::Launcher => {
self.runners = result.join("runners");
self.dxvks = result.join("dxvks");
self.prefix = result.join("prefix");
self.game = result.join(concat!("Hon", "kai Sta", "r Rail"));
self.components = result.join("components");
self.patch = result.join("patch");
self.temp = result.clone();
self.runners = result.join("runners");
self.dxvks = result.join("dxvks");
self.prefix = result.join("prefix");
self.game_global = result.join("HSR");
self.game_china = result.join("HSR China"); // TODO change this
self.components = result.join("components");
self.patch = result.join("patch");
self.temp = result.clone();
self.launcher = result;
}
Folders::Runners => self.runners = result,
Folders::DXVK => self.dxvks = result,
Folders::Prefix => self.prefix = result,
Folders::Game => self.game = result,
Folders::Components => self.components = result,
Folders::Patch => self.patch = result,
Folders::Temp => self.temp = result
Folders::Runners => self.runners = result,
Folders::DXVK => self.dxvks = result,
Folders::Prefix => self.prefix = result,
Folders::GameGlobal => self.game_global = result,
Folders::GameChina => self.game_china = result,
Folders::Components => self.components = result,
Folders::Patch => self.patch = result,
Folders::Temp => self.temp = result
}
}
}
@ -339,7 +355,8 @@ impl SimpleAsyncComponent for DefaultPathsApp {
(old_config.game.wine.builds, &self.runners),
(old_config.game.dxvk.builds, &self.dxvks),
(old_config.game.wine.prefix, &self.prefix),
(old_config.game.path, &self.game),
(old_config.game.path.global, &self.game_global),
(old_config.game.path.china, &self.game_china),
(old_config.components.path, &self.components),
(old_config.patch.path, &self.patch)
];
@ -399,7 +416,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

@ -18,7 +18,9 @@ pub fn apply_patch(sender: ComponentSender<App>, patch: MainPatch) {
std::thread::spawn(move || {
let mut apply_patch_if_needed = true;
if let Err(err) = patch.apply(config.game.path, config.patch.root) {
let game_path = config.game.path.for_edition(config.launcher.edition);
if let Err(err) = patch.apply(game_path, config.patch.root) {
tracing::error!("Failed to patch the game");
sender.input(AppMsg::Toast {

View file

@ -17,8 +17,9 @@ 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();
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 {
DiffUpdate::InstallerUpdate(InstallerUpdate::DownloadingError(err)) => {
tracing::error!("Downloading failed: {err}");

View file

@ -530,8 +530,8 @@ impl SimpleComponent for App {
group.add_action::<GameFolder>(&RelmAction::new_stateless(clone!(@strong sender => move |_| {
let path = match Config::get() {
Ok(config) => config.game.path,
Err(_) => CONFIG.game.path.clone()
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) {

View file

@ -22,6 +22,8 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
std::thread::spawn(move || {
match repairer::try_get_integrity_files(None) {
Ok(files) => {
let game_path = config.game.path.for_edition(config.launcher.edition).to_path_buf();
progress_bar_input.send(ProgressBarMsg::UpdateProgress(0, 0));
let mut total = 0;
@ -52,7 +54,7 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
let thread_sender = verify_sender.clone();
std::thread::spawn(clone!(@strong config.game.path as game_path => 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)
@ -94,7 +96,7 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
let total = broken.len() as f64;
let main_patch = MainPatch::from_folder(&config.patch.path).unwrap()
.is_applied(&config.game.path).unwrap();
.is_applied(&game_path).unwrap();
tracing::debug!("Patch status: {main_patch}");
@ -115,7 +117,7 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
if !should_ignore(&file.path, main_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

@ -311,8 +311,8 @@ impl SimpleAsyncComponent for GeneralApp {
PatchStatus::Available { .. } => unsafe {
let path = match Config::get() {
Ok(config) => config.game.path,
Err(_) => CONFIG.game.path.clone(),
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.main_patch.as_ref().unwrap_unchecked().is_applied(path) {
@ -337,8 +337,8 @@ impl SimpleAsyncComponent for GeneralApp {
PatchStatus::Testing { .. } => tr("patch-testing-tooltip"),
PatchStatus::Available { .. } => unsafe {
let path = match Config::get() {
Ok(config) => config.game.path,
Err(_) => CONFIG.game.path.clone(),
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.main_patch.as_ref().unwrap_unchecked().is_applied(path) {