use std::{path::PathBuf, sync::Arc};
use downloader::progress::Reporter;
use log::{debug, info};
use tokio::fs::create_dir_all;
use wincompatlib::prelude::*;
use crate::{
components::{
component_downloader::ComponentDownloader, dxvk_component::DXVKComponent,
game_component::GameComponent, proton_component::ProtonComponent,
},
game_patcher,
game_state::GameState,
utils::{get_game_name, get_game_name_with_executable, github_requester::GithubRequester},
};
pub struct GameManager;
impl GameManager {
pub async fn install_wine
(
config_dir: PathBuf,
release_index: usize,
progress: Option>,
) -> anyhow::Result
where
P: Reporter + 'static,
{
let mut wine_component = ProtonComponent::new(config_dir);
wine_component.set_github_release_index(release_index);
wine_component.install(progress).await?;
let mut config = GameState::get_config().await;
config.is_wine_installed = true;
GameState::save_config(config).await?;
Ok(wine_component)
}
pub async fn install_dxvk(
proton: &Proton,
config_dir: PathBuf,
release_index: usize,
progress: Option>,
) -> anyhow::Result<()>
where
P: Reporter + 'static,
{
let mut dxvk_component = DXVKComponent::from_wine(proton.wine(), config_dir);
dxvk_component.set_github_release_index(release_index);
dxvk_component.install(progress).await?;
let mut config = GameState::get_config().await;
config.is_dxvk_installed = true;
GameState::save_config(config).await?;
Ok(())
}
pub async fn install_font(proton: &Proton, progress: Option>) -> anyhow::Result<()>
where
P: Reporter + 'static,
{
let wine_with_proton_prefix = proton // wine take the data/wine/pfx prefix, but we want the data/wine prefix
.wine()
.clone()
.with_prefix(proton.wine().prefix.parent().unwrap());
if let Some(p) = &progress {
p.setup(Some(10), "");
}
notify_fonts_progress(0, &progress);
wine_with_proton_prefix.install_font(Font::Arial)?;
notify_fonts_progress(1, &progress);
wine_with_proton_prefix.install_font(Font::Andale)?;
notify_fonts_progress(2, &progress);
wine_with_proton_prefix.install_font(Font::Courier)?;
notify_fonts_progress(3, &progress);
wine_with_proton_prefix.install_font(Font::ComicSans)?;
notify_fonts_progress(4, &progress);
wine_with_proton_prefix.install_font(Font::Georgia)?;
notify_fonts_progress(5, &progress);
wine_with_proton_prefix.install_font(Font::Impact)?;
notify_fonts_progress(6, &progress);
wine_with_proton_prefix.install_font(Font::Times)?;
notify_fonts_progress(7, &progress);
wine_with_proton_prefix.install_font(Font::Trebuchet)?;
notify_fonts_progress(8, &progress);
wine_with_proton_prefix.install_font(Font::Verdana)?;
notify_fonts_progress(9, &progress);
wine_with_proton_prefix.install_font(Font::Webdings)?;
notify_fonts_progress(10, &progress);
let mut config = GameState::get_config().await;
config.is_font_installed = true;
GameState::save_config(config).await?;
Ok(())
}
pub async fn install_dependencies(proton: &Proton) -> anyhow::Result<()> {
let wine_with_proton_prefix = proton // wine take the data/wine/pfx prefix, but we want the data/wine prefix
.wine()
.clone()
.with_prefix(proton.wine().prefix.parent().unwrap());
let winetricks = Winetricks::from_wine("/bin/winetricks", wine_with_proton_prefix);
//winetricks.install("corefonts")?;
let mut child = winetricks.install("vcrun2022")?;
child
.wait()
.expect("Something failed when waiting for the installation");
let mut config = GameState::get_config().await;
config.is_dependecies_installed = true;
GameState::save_config(config).await?;
Ok(())
}
pub async fn install_game(game_dir: PathBuf, progress: Arc
) -> anyhow::Result<()>
where
P: Reporter + 'static,
{
let _ = create_dir_all(game_dir.clone()).await;
let game_component = GameComponent::new(game_dir);
game_component.install(Some(progress)).await?;
let mut config = GameState::get_config().await;
config.is_game_installed = true;
GameState::save_config(config).await?;
Ok(())
}
// this function just pass is_game_installed and is_game_patched to false,
// so the launcher on the next iteration download the new file and delete the old one with the check process in the installation process
pub async fn update_game() -> anyhow::Result<()> {
let mut config = GameState::get_config().await;
config.is_game_installed = false;
config.is_game_patched = false;
GameState::save_config(config).await?;
Ok(())
}
pub async fn patch_game(game_dir: PathBuf) -> anyhow::Result<()> {
game_patcher::patch_game(game_dir).await?;
Ok(())
}
pub async fn start_game(proton: &Proton, game_dir: PathBuf) {
debug!("Wine version : {:?}", proton.wine().version().unwrap());
let mut child = proton
.run(
game_dir
.join(get_game_name())
.join(get_game_name_with_executable()),
)
.unwrap();
child.wait().expect("The game failed to run");
}
}
fn notify_fonts_progress
(nbr: u64, progress: &Option>)
where
P: Reporter + 'static,
{
info!("{}", format!("{}/10 font installed", nbr));
if let Some(p) = progress {
p.progress(nbr);
}
}