can now install specific version of Proton GE and DXVK

This commit is contained in:
ALEZ-DEV 2024-05-14 20:20:02 +02:00
parent 66146b10f8
commit d7eebbc904
9 changed files with 162 additions and 25 deletions

View File

@ -14,7 +14,9 @@ name = "babylonia-terminal-cli"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.83"
babylonia-terminal-sdk = { path = "./../babylonia-terminal-sdk" }
dialoguer = "0.11.0"
downloader = { git = "https://github.com/ALEZ-DEV/downloader" } # version = "0.2.7",
indicatif = "0.17.8"
log = "0.4.21"

View File

@ -1,7 +1,12 @@
use std::{path::PathBuf, str::FromStr};
use babylonia_terminal_sdk::{
components::proton_component::ProtonComponent, game_manager::GameManager, game_state::GameState,
components::{
dxvk_component::{DXVK_DEV, DXVK_REPO},
proton_component::{ProtonComponent, PROTON_DEV, PROTON_REPO},
},
game_manager::GameManager,
game_state::GameState,
};
use log::{debug, info, LevelFilter};
use simple_logger::SimpleLogger;
@ -9,6 +14,7 @@ use tokio::io::{AsyncBufReadExt, BufReader};
use wincompatlib::prelude::*;
pub mod reporter;
pub mod utils;
use crate::reporter::DownloadReporter;
@ -49,10 +55,24 @@ async fn main() {
match state {
GameState::ProtonNotInstalled => {
let release;
if utils::use_latest("Do you want to install latest version of Proton GE or a specific version of it?") {
release = 0;
} else {
release = utils::choose_release_version(
PROTON_DEV,
PROTON_REPO,
"Please, select a version of Proton GE to install.",
)
.await
.expect("Failed to fetch proton version!");
}
info!("Proton not installed, installing it...");
proton_component = Some(
GameManager::install_wine(
GameState::get_config_directory().await,
release,
Some(DownloadReporter::create(false)),
)
.await
@ -61,11 +81,27 @@ async fn main() {
info!("Proton installed");
}
GameState::DXVKNotInstalled => {
let release;
if utils::use_latest(
"Do you want to install latest version of DXVK or a specific version of it?",
) {
release = 0;
} else {
release = utils::choose_release_version(
DXVK_DEV,
DXVK_REPO,
"Please, select a version of DXVK to install.",
)
.await
.expect("Failed to fetch DXVK version!");
}
info!("DXVK not installed, installing it...");
debug!("{:?}", proton_component);
GameManager::install_dxvk(
&proton.clone().unwrap(),
GameState::get_config_directory().await,
release,
Some(DownloadReporter::create(false)),
)
.await

View File

@ -0,0 +1,43 @@
use babylonia_terminal_sdk::utils::github_requester::GithubRequester;
use dialoguer::{theme::ColorfulTheme, Select};
pub fn use_latest(prompt: &str) -> bool {
let choices = ["Install latest", "Choose specific version"];
let index = Select::with_theme(&ColorfulTheme::default())
.with_prompt(prompt)
.default(0)
.items(&choices)
.interact()
.unwrap();
if choices[index] == "Install latest" {
true
} else {
false
}
}
struct Chooser;
impl GithubRequester for Chooser {
fn set_github_release_index(&mut self, _: usize) {}
}
pub async fn choose_release_version(
github_username: &str,
repo_name: &str,
prompt: &str,
) -> anyhow::Result<usize> {
let releases = Chooser::get_github_releases(github_username, repo_name).await?;
let releases_names: Vec<String> = releases.iter().map(|r| r.tag_name.to_owned()).collect();
let index = Select::with_theme(&ColorfulTheme::default())
.with_prompt(prompt)
.default(0)
.items(&releases_names)
.max_length(5)
.interact()
.unwrap();
Ok(index)
}

View File

@ -9,6 +9,7 @@ pub trait ComponentDownloader {
//the 'static is something to change, I don't very like it, but it's for testing purpose
#[allow(async_fn_in_trait)]
async fn download<P: Reporter + 'static>(
&self,
output_dir: &PathBuf,
progress: Option<Arc<P>>,
) -> anyhow::Result<PathBuf>;

View File

@ -16,9 +16,13 @@ use crate::utils::github_requester::GithubRequester;
use super::component_downloader::ComponentDownloader;
pub static DXVK_DEV: &str = "doitsujin";
pub static DXVK_REPO: &str = "dxvk";
pub struct DXVKComponent<'a> {
wine: &'a Wine,
path: PathBuf,
github_release_index: usize,
}
impl<'a> DXVKComponent<'a> {
@ -26,11 +30,16 @@ impl<'a> DXVKComponent<'a> {
DXVKComponent {
wine,
path: path.join("dxvk"),
github_release_index: 0,
}
}
}
impl<'a> GithubRequester for DXVKComponent<'a> {}
impl<'a> GithubRequester for DXVKComponent<'a> {
fn set_github_release_index(&mut self, new_release_index: usize) {
self.github_release_index = new_release_index;
}
}
impl<'a> ComponentDownloader for DXVKComponent<'a> {
async fn install<P: downloader::progress::Reporter + 'static>(
@ -42,7 +51,7 @@ impl<'a> ComponentDownloader for DXVKComponent<'a> {
.parent()
.expect("Failed to get parent folder for DXVK")
.to_path_buf();
let file_output = Self::download(&dir, progress).await?;
let file_output = self.download(&dir, progress).await?;
Self::uncompress(file_output.clone(), self.path.clone()).await?;
@ -64,12 +73,15 @@ impl<'a> ComponentDownloader for DXVKComponent<'a> {
}
async fn download<P: downloader::progress::Reporter + 'static>(
&self,
output_dir: &std::path::PathBuf,
progress: Option<std::sync::Arc<P>>,
) -> anyhow::Result<std::path::PathBuf> {
let releases = Self::get_latest_github_release("doitsujin", "dxvk").await?;
let releases =
Self::get_github_release_version(DXVK_DEV, DXVK_REPO, self.github_release_index)
.await?;
let asset = releases[0]
let asset = releases
.assets
.first()
.expect("Asset not found in the github release");

View File

@ -90,7 +90,9 @@ impl GameComponent {
}
}
impl GithubRequester for GameComponent {}
impl GithubRequester for GameComponent {
fn set_github_release_index(&mut self, _: usize) {}
}
impl ComponentDownloader for GameComponent {
async fn install<P: downloader::progress::Reporter + 'static>(
@ -98,12 +100,13 @@ impl ComponentDownloader for GameComponent {
progress: Option<std::sync::Arc<P>>,
) -> anyhow::Result<()> {
let _ = create_dir_all(&self.game_dir).await;
Self::download(&self.game_dir, progress).await?;
self.download(&self.game_dir, progress).await?;
Ok(())
}
async fn download<P: downloader::progress::Reporter + 'static>(
&self,
output_dir: &std::path::PathBuf,
progress: Option<std::sync::Arc<P>>,
) -> anyhow::Result<std::path::PathBuf> {
@ -179,6 +182,6 @@ impl ComponentDownloader for GameComponent {
_file: std::path::PathBuf,
_new_filename: std::path::PathBuf,
) -> anyhow::Result<()> {
panic!("How did you run this function??!!")
anyhow::bail!("How did you run this function??!!")
}
}

View File

@ -14,37 +14,48 @@ use wincompatlib::wine::ext::WineBootExt;
use super::component_downloader::ComponentDownloader;
use crate::utils::github_requester::GithubRequester;
pub static PROTON_DEV: &str = "GloriousEggroll";
pub static PROTON_REPO: &str = "proton-ge-custom";
#[derive(Debug, PartialEq, Eq)]
pub struct ProtonComponent {
path: PathBuf,
github_release_index: usize,
}
impl GithubRequester for ProtonComponent {}
impl GithubRequester for ProtonComponent {
fn set_github_release_index(&mut self, new_release_index: usize) {
self.github_release_index = new_release_index;
}
}
impl ComponentDownloader for ProtonComponent {
async fn install<P: Reporter + 'static>(&self, progress: Option<Arc<P>>) -> anyhow::Result<()> {
let file_output = Self::download(
&self
.path
.parent()
.expect("Failed to get the parent directory of Wine")
.to_path_buf(),
progress,
)
.await?;
let file_output = self
.download(
&self
.path
.parent()
.expect("Failed to get the parent directory of Wine")
.to_path_buf(),
progress,
)
.await?;
Self::uncompress(file_output.clone(), self.path.clone()).await?;
Ok(())
}
async fn download<P: Reporter + 'static>(
&self,
output_dir: &PathBuf,
progress: Option<Arc<P>>,
) -> anyhow::Result<PathBuf> {
let release =
Self::get_latest_github_release("GloriousEggroll", "proton-ge-custom").await?;
Self::get_github_release_version(PROTON_DEV, PROTON_REPO, self.github_release_index)
.await?;
let asset = release[0]
let asset = release
.assets
.get(1)
.expect("Asset not found in the github release");
@ -91,6 +102,7 @@ impl ProtonComponent {
pub fn new(path: PathBuf) -> Self {
ProtonComponent {
path: path.join("proton"),
github_release_index: 0,
}
}

View File

@ -12,7 +12,7 @@ use crate::{
},
game_patcher,
game_state::GameState,
utils::{get_game_name, get_game_name_with_executable},
utils::{get_game_name, get_game_name_with_executable, github_requester::GithubRequester},
};
pub struct GameManager;
@ -20,12 +20,14 @@ pub struct GameManager;
impl GameManager {
pub async fn install_wine<P>(
config_dir: PathBuf,
release_index: usize,
progress: Option<Arc<P>>,
) -> anyhow::Result<ProtonComponent>
where
P: Reporter + 'static,
{
let wine_component = ProtonComponent::new(config_dir);
let mut wine_component = ProtonComponent::new(config_dir);
wine_component.set_github_release_index(release_index);
wine_component.install(progress).await?;
@ -39,12 +41,15 @@ impl GameManager {
pub async fn install_dxvk<P>(
proton: &Proton,
config_dir: PathBuf,
release_index: usize,
progress: Option<Arc<P>>,
) -> anyhow::Result<()>
where
P: Reporter + 'static,
{
let dxvk_component = DXVKComponent::from_wine(proton.wine(), config_dir);
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;
@ -107,7 +112,11 @@ impl GameManager {
let winetricks = Winetricks::from_wine("/bin/winetricks", wine_with_proton_prefix);
//winetricks.install("corefonts")?;
winetricks.install("vcrun2022")?;
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;

View File

@ -64,7 +64,7 @@ pub trait GithubRequester {
}
#[allow(async_fn_in_trait)]
async fn get_latest_github_release(
async fn get_github_releases(
user: &str,
repo_name: &str,
) -> anyhow::Result<Vec<GithubRelease>> {
@ -80,4 +80,23 @@ pub trait GithubRequester {
let releases: Vec<GithubRelease> = serde_json::from_str(&body)?;
Ok(releases)
}
#[allow(async_fn_in_trait)]
async fn get_github_release_version(
user: &str,
repo_name: &str,
release_index: usize,
) -> anyhow::Result<GithubRelease> {
let releases = Self::get_github_releases(user, repo_name).await?;
let release = releases.get(release_index);
if release.is_none() {
anyhow::bail!("Wrong index when trying to get the github release");
}
Ok(release.unwrap().to_owned())
}
fn set_github_release_index(&mut self, new_release_index: usize);
}