mirror of
https://github.com/ALEZ-DEV/Babylonia-terminal.git
synced 2025-12-16 01:18:50 +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
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow = "1.0.83"
|
||||||
babylonia-terminal-sdk = { path = "./../babylonia-terminal-sdk" }
|
babylonia-terminal-sdk = { path = "./../babylonia-terminal-sdk" }
|
||||||
|
dialoguer = "0.11.0"
|
||||||
downloader = { git = "https://github.com/ALEZ-DEV/downloader" } # version = "0.2.7",
|
downloader = { git = "https://github.com/ALEZ-DEV/downloader" } # version = "0.2.7",
|
||||||
indicatif = "0.17.8"
|
indicatif = "0.17.8"
|
||||||
log = "0.4.21"
|
log = "0.4.21"
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
use std::{path::PathBuf, str::FromStr};
|
use std::{path::PathBuf, str::FromStr};
|
||||||
|
|
||||||
use babylonia_terminal_sdk::{
|
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 log::{debug, info, LevelFilter};
|
||||||
use simple_logger::SimpleLogger;
|
use simple_logger::SimpleLogger;
|
||||||
@ -9,6 +14,7 @@ use tokio::io::{AsyncBufReadExt, BufReader};
|
|||||||
use wincompatlib::prelude::*;
|
use wincompatlib::prelude::*;
|
||||||
|
|
||||||
pub mod reporter;
|
pub mod reporter;
|
||||||
|
pub mod utils;
|
||||||
|
|
||||||
use crate::reporter::DownloadReporter;
|
use crate::reporter::DownloadReporter;
|
||||||
|
|
||||||
@ -49,10 +55,24 @@ async fn main() {
|
|||||||
|
|
||||||
match state {
|
match state {
|
||||||
GameState::ProtonNotInstalled => {
|
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...");
|
info!("Proton not installed, installing it...");
|
||||||
proton_component = Some(
|
proton_component = Some(
|
||||||
GameManager::install_wine(
|
GameManager::install_wine(
|
||||||
GameState::get_config_directory().await,
|
GameState::get_config_directory().await,
|
||||||
|
release,
|
||||||
Some(DownloadReporter::create(false)),
|
Some(DownloadReporter::create(false)),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@ -61,11 +81,27 @@ async fn main() {
|
|||||||
info!("Proton installed");
|
info!("Proton installed");
|
||||||
}
|
}
|
||||||
GameState::DXVKNotInstalled => {
|
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...");
|
info!("DXVK not installed, installing it...");
|
||||||
debug!("{:?}", proton_component);
|
debug!("{:?}", proton_component);
|
||||||
GameManager::install_dxvk(
|
GameManager::install_dxvk(
|
||||||
&proton.clone().unwrap(),
|
&proton.clone().unwrap(),
|
||||||
GameState::get_config_directory().await,
|
GameState::get_config_directory().await,
|
||||||
|
release,
|
||||||
Some(DownloadReporter::create(false)),
|
Some(DownloadReporter::create(false)),
|
||||||
)
|
)
|
||||||
.await
|
.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
|
//the 'static is something to change, I don't very like it, but it's for testing purpose
|
||||||
#[allow(async_fn_in_trait)]
|
#[allow(async_fn_in_trait)]
|
||||||
async fn download<P: Reporter + 'static>(
|
async fn download<P: Reporter + 'static>(
|
||||||
|
&self,
|
||||||
output_dir: &PathBuf,
|
output_dir: &PathBuf,
|
||||||
progress: Option<Arc<P>>,
|
progress: Option<Arc<P>>,
|
||||||
) -> anyhow::Result<PathBuf>;
|
) -> anyhow::Result<PathBuf>;
|
||||||
|
|||||||
@ -16,9 +16,13 @@ use crate::utils::github_requester::GithubRequester;
|
|||||||
|
|
||||||
use super::component_downloader::ComponentDownloader;
|
use super::component_downloader::ComponentDownloader;
|
||||||
|
|
||||||
|
pub static DXVK_DEV: &str = "doitsujin";
|
||||||
|
pub static DXVK_REPO: &str = "dxvk";
|
||||||
|
|
||||||
pub struct DXVKComponent<'a> {
|
pub struct DXVKComponent<'a> {
|
||||||
wine: &'a Wine,
|
wine: &'a Wine,
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
|
github_release_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DXVKComponent<'a> {
|
impl<'a> DXVKComponent<'a> {
|
||||||
@ -26,11 +30,16 @@ impl<'a> DXVKComponent<'a> {
|
|||||||
DXVKComponent {
|
DXVKComponent {
|
||||||
wine,
|
wine,
|
||||||
path: path.join("dxvk"),
|
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> {
|
impl<'a> ComponentDownloader for DXVKComponent<'a> {
|
||||||
async fn install<P: downloader::progress::Reporter + 'static>(
|
async fn install<P: downloader::progress::Reporter + 'static>(
|
||||||
@ -42,7 +51,7 @@ impl<'a> ComponentDownloader for DXVKComponent<'a> {
|
|||||||
.parent()
|
.parent()
|
||||||
.expect("Failed to get parent folder for DXVK")
|
.expect("Failed to get parent folder for DXVK")
|
||||||
.to_path_buf();
|
.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?;
|
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>(
|
async fn download<P: downloader::progress::Reporter + 'static>(
|
||||||
|
&self,
|
||||||
output_dir: &std::path::PathBuf,
|
output_dir: &std::path::PathBuf,
|
||||||
progress: Option<std::sync::Arc<P>>,
|
progress: Option<std::sync::Arc<P>>,
|
||||||
) -> anyhow::Result<std::path::PathBuf> {
|
) -> 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
|
.assets
|
||||||
.first()
|
.first()
|
||||||
.expect("Asset not found in the github release");
|
.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 {
|
impl ComponentDownloader for GameComponent {
|
||||||
async fn install<P: downloader::progress::Reporter + 'static>(
|
async fn install<P: downloader::progress::Reporter + 'static>(
|
||||||
@ -98,12 +100,13 @@ impl ComponentDownloader for GameComponent {
|
|||||||
progress: Option<std::sync::Arc<P>>,
|
progress: Option<std::sync::Arc<P>>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let _ = create_dir_all(&self.game_dir).await;
|
let _ = create_dir_all(&self.game_dir).await;
|
||||||
Self::download(&self.game_dir, progress).await?;
|
self.download(&self.game_dir, progress).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn download<P: downloader::progress::Reporter + 'static>(
|
async fn download<P: downloader::progress::Reporter + 'static>(
|
||||||
|
&self,
|
||||||
output_dir: &std::path::PathBuf,
|
output_dir: &std::path::PathBuf,
|
||||||
progress: Option<std::sync::Arc<P>>,
|
progress: Option<std::sync::Arc<P>>,
|
||||||
) -> anyhow::Result<std::path::PathBuf> {
|
) -> anyhow::Result<std::path::PathBuf> {
|
||||||
@ -179,6 +182,6 @@ impl ComponentDownloader for GameComponent {
|
|||||||
_file: std::path::PathBuf,
|
_file: std::path::PathBuf,
|
||||||
_new_filename: std::path::PathBuf,
|
_new_filename: std::path::PathBuf,
|
||||||
) -> anyhow::Result<()> {
|
) -> 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 super::component_downloader::ComponentDownloader;
|
||||||
use crate::utils::github_requester::GithubRequester;
|
use crate::utils::github_requester::GithubRequester;
|
||||||
|
|
||||||
|
pub static PROTON_DEV: &str = "GloriousEggroll";
|
||||||
|
pub static PROTON_REPO: &str = "proton-ge-custom";
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct ProtonComponent {
|
pub struct ProtonComponent {
|
||||||
path: PathBuf,
|
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 {
|
impl ComponentDownloader for ProtonComponent {
|
||||||
async fn install<P: Reporter + 'static>(&self, progress: Option<Arc<P>>) -> anyhow::Result<()> {
|
async fn install<P: Reporter + 'static>(&self, progress: Option<Arc<P>>) -> anyhow::Result<()> {
|
||||||
let file_output = Self::download(
|
let file_output = self
|
||||||
&self
|
.download(
|
||||||
.path
|
&self
|
||||||
.parent()
|
.path
|
||||||
.expect("Failed to get the parent directory of Wine")
|
.parent()
|
||||||
.to_path_buf(),
|
.expect("Failed to get the parent directory of Wine")
|
||||||
progress,
|
.to_path_buf(),
|
||||||
)
|
progress,
|
||||||
.await?;
|
)
|
||||||
|
.await?;
|
||||||
Self::uncompress(file_output.clone(), self.path.clone()).await?;
|
Self::uncompress(file_output.clone(), self.path.clone()).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn download<P: Reporter + 'static>(
|
async fn download<P: Reporter + 'static>(
|
||||||
|
&self,
|
||||||
output_dir: &PathBuf,
|
output_dir: &PathBuf,
|
||||||
progress: Option<Arc<P>>,
|
progress: Option<Arc<P>>,
|
||||||
) -> anyhow::Result<PathBuf> {
|
) -> anyhow::Result<PathBuf> {
|
||||||
let release =
|
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
|
.assets
|
||||||
.get(1)
|
.get(1)
|
||||||
.expect("Asset not found in the github release");
|
.expect("Asset not found in the github release");
|
||||||
@ -91,6 +102,7 @@ impl ProtonComponent {
|
|||||||
pub fn new(path: PathBuf) -> Self {
|
pub fn new(path: PathBuf) -> Self {
|
||||||
ProtonComponent {
|
ProtonComponent {
|
||||||
path: path.join("proton"),
|
path: path.join("proton"),
|
||||||
|
github_release_index: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
game_patcher,
|
game_patcher,
|
||||||
game_state::GameState,
|
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;
|
pub struct GameManager;
|
||||||
@ -20,12 +20,14 @@ pub struct GameManager;
|
|||||||
impl GameManager {
|
impl GameManager {
|
||||||
pub async fn install_wine<P>(
|
pub async fn install_wine<P>(
|
||||||
config_dir: PathBuf,
|
config_dir: PathBuf,
|
||||||
|
release_index: usize,
|
||||||
progress: Option<Arc<P>>,
|
progress: Option<Arc<P>>,
|
||||||
) -> anyhow::Result<ProtonComponent>
|
) -> anyhow::Result<ProtonComponent>
|
||||||
where
|
where
|
||||||
P: Reporter + 'static,
|
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?;
|
wine_component.install(progress).await?;
|
||||||
|
|
||||||
@ -39,12 +41,15 @@ impl GameManager {
|
|||||||
pub async fn install_dxvk<P>(
|
pub async fn install_dxvk<P>(
|
||||||
proton: &Proton,
|
proton: &Proton,
|
||||||
config_dir: PathBuf,
|
config_dir: PathBuf,
|
||||||
|
release_index: usize,
|
||||||
progress: Option<Arc<P>>,
|
progress: Option<Arc<P>>,
|
||||||
) -> anyhow::Result<()>
|
) -> anyhow::Result<()>
|
||||||
where
|
where
|
||||||
P: Reporter + 'static,
|
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?;
|
dxvk_component.install(progress).await?;
|
||||||
|
|
||||||
let mut config = GameState::get_config().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);
|
let winetricks = Winetricks::from_wine("/bin/winetricks", wine_with_proton_prefix);
|
||||||
//winetricks.install("corefonts")?;
|
//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;
|
let mut config = GameState::get_config().await;
|
||||||
config.is_dependecies_installed = true;
|
config.is_dependecies_installed = true;
|
||||||
|
|||||||
@ -64,7 +64,7 @@ pub trait GithubRequester {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(async_fn_in_trait)]
|
#[allow(async_fn_in_trait)]
|
||||||
async fn get_latest_github_release(
|
async fn get_github_releases(
|
||||||
user: &str,
|
user: &str,
|
||||||
repo_name: &str,
|
repo_name: &str,
|
||||||
) -> anyhow::Result<Vec<GithubRelease>> {
|
) -> anyhow::Result<Vec<GithubRelease>> {
|
||||||
@ -80,4 +80,23 @@ pub trait GithubRequester {
|
|||||||
let releases: Vec<GithubRelease> = serde_json::from_str(&body)?;
|
let releases: Vec<GithubRelease> = serde_json::from_str(&body)?;
|
||||||
Ok(releases)
|
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