mirror of
https://github.com/ALEZ-DEV/Babylonia-terminal.git
synced 2025-12-15 08:58:51 +00:00
can now install specific version of Proton GE and DXVK
This commit is contained in:
parent
66146b10f8
commit
d7eebbc904
@ -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"
|
||||
|
||||
@ -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
|
||||
|
||||
43
babylonia-terminal-cli/src/utils.rs
Normal file
43
babylonia-terminal-cli/src/utils.rs
Normal 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)
|
||||
}
|
||||
@ -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>;
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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??!!")
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user