0.3.0
- added support for dynamic components loading
This commit is contained in:
parent
9d6aeff526
commit
42b738dc1e
10 changed files with 200 additions and 111 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,6 +1,3 @@
|
|||
[submodule "anime-game-core"]
|
||||
path = anime-game-core
|
||||
url = https://github.com/an-anime-team/anime-game-core
|
||||
[submodule "components"]
|
||||
path = components
|
||||
url = https://github.com/an-anime-team/components
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "anime-launcher-sdk"
|
||||
version = "0.2.5"
|
||||
version = "0.3.0"
|
||||
authors = ["Nikita Podvirnyy <suimin.tu.mu.ga.mi@gmail.com>"]
|
||||
license = "GPL-3.0"
|
||||
readme = "README.md"
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit a90aae53797802b458670bd99428cd258ac1d902
|
||||
Subproject commit 33dce6a6d0202e1f8b17a8193603cc05c4d6a5ef
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 50c93220b16ef7609f61fc0785a1e435683d4a0c
|
|
@ -3,22 +3,12 @@ use std::path::PathBuf;
|
|||
use serde::{Serialize, Deserialize};
|
||||
use wincompatlib::prelude::*;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref GROUPS: Vec<Group> = vec![
|
||||
Group {
|
||||
name: String::from("Vanilla"),
|
||||
versions: serde_json::from_str::<Vec<Version>>(include_str!("../../components/dxvk/vanilla.json")).unwrap().into_iter().take(12).collect()
|
||||
},
|
||||
Group {
|
||||
name: String::from("Async"),
|
||||
versions: serde_json::from_str::<Vec<Version>>(include_str!("../../components/dxvk/async.json")).unwrap().into_iter().take(12).collect()
|
||||
}
|
||||
];
|
||||
}
|
||||
use super::loader::ComponentsLoader;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct Group {
|
||||
pub name: String,
|
||||
pub title: String,
|
||||
pub versions: Vec<Version>
|
||||
}
|
||||
|
||||
|
@ -26,25 +16,23 @@ pub struct Group {
|
|||
pub struct Version {
|
||||
pub name: String,
|
||||
pub version: String,
|
||||
pub uri: String,
|
||||
pub recommended: bool
|
||||
pub uri: String
|
||||
}
|
||||
|
||||
impl Version {
|
||||
/// Get latest recommended dxvk version
|
||||
#[inline]
|
||||
pub fn latest() -> Self {
|
||||
get_groups()[0].versions[0].clone()
|
||||
pub fn latest<T: Into<PathBuf>>(components: T) -> anyhow::Result<Self> {
|
||||
Ok(get_groups(components)?[0].versions[0].clone())
|
||||
}
|
||||
|
||||
/// Check is current dxvk downloaded in specified folder
|
||||
#[inline]
|
||||
pub fn is_downloaded_in<T: Into<PathBuf> + std::fmt::Debug>(&self, folder: T) -> bool {
|
||||
pub fn is_downloaded_in<T: Into<PathBuf>>(&self, folder: T) -> bool {
|
||||
folder.into().join(&self.name).exists()
|
||||
}
|
||||
|
||||
/// Install current dxvk
|
||||
#[tracing::instrument(level = "debug")]
|
||||
#[tracing::instrument(level = "debug", ret)]
|
||||
#[inline]
|
||||
pub fn install<T: Into<PathBuf> + std::fmt::Debug>(&self, dxvks_folder: T, wine: &Wine, params: InstallParams) -> std::io::Result<()> {
|
||||
tracing::debug!("Installing DXVK");
|
||||
|
@ -57,7 +45,7 @@ impl Version {
|
|||
}
|
||||
|
||||
/// Uninstall current dxvk
|
||||
#[tracing::instrument(level = "debug")]
|
||||
#[tracing::instrument(level = "debug", ret)]
|
||||
#[inline]
|
||||
pub fn uninstall(&self, wine: &Wine, params: InstallParams) -> std::io::Result<()> {
|
||||
tracing::debug!("Uninstalling DXVK");
|
||||
|
@ -69,17 +57,15 @@ impl Version {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get dxvk groups
|
||||
#[inline]
|
||||
pub fn get_groups() -> Vec<Group> {
|
||||
GROUPS.clone()
|
||||
pub fn get_groups<T: Into<PathBuf>>(components: T) -> anyhow::Result<Vec<Group>> {
|
||||
ComponentsLoader::new(components).get_dxvk_versions()
|
||||
}
|
||||
|
||||
/// List downloaded dxvk versions in some specific folder
|
||||
pub fn get_downloaded<T: Into<PathBuf>>(folder: T) -> std::io::Result<Vec<Version>> {
|
||||
pub fn get_downloaded<T: Into<PathBuf>>(components: T, folder: T) -> anyhow::Result<Vec<Version>> {
|
||||
let mut downloaded = Vec::new();
|
||||
|
||||
let list = get_groups()
|
||||
let list = get_groups(components)?
|
||||
.into_iter()
|
||||
.flat_map(|group| group.versions)
|
||||
.collect::<Vec<Version>>();
|
||||
|
|
|
@ -1 +1,148 @@
|
|||
// TODO
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::anime_game_core::traits::git_sync::RemoteGitSync;
|
||||
use super::wine;
|
||||
use super::dxvk;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ComponentsLoader {
|
||||
folder: PathBuf
|
||||
}
|
||||
|
||||
impl RemoteGitSync for ComponentsLoader {
|
||||
fn folder(&self) -> &Path {
|
||||
self.folder.as_path()
|
||||
}
|
||||
}
|
||||
|
||||
impl ComponentsLoader {
|
||||
pub fn new<T: Into<PathBuf>>(folder: T) -> Self {
|
||||
Self {
|
||||
folder: folder.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to get wine versions from components index
|
||||
#[tracing::instrument(level = "debug", ret)]
|
||||
pub fn get_wine_versions(&self) -> anyhow::Result<Vec<wine::Group>> {
|
||||
tracing::debug!("Getting wine versions");
|
||||
|
||||
let components = serde_json::from_str::<serde_json::Value>(&std::fs::read_to_string(self.folder.join("components.json"))?)?;
|
||||
|
||||
match components.get("wine") {
|
||||
Some(wine) => match wine.as_array() {
|
||||
Some(groups) => {
|
||||
let mut wine_groups = Vec::with_capacity(groups.len());
|
||||
|
||||
for group in groups {
|
||||
let name = match group.get("name") {
|
||||
Some(name) => match name.as_str() {
|
||||
Some(name) => name.to_string(),
|
||||
None => anyhow::bail!("Wrong components index structure: wine group's name entry must be a string")
|
||||
}
|
||||
|
||||
None => anyhow::bail!("Wrong components index structure: wine group's name not found")
|
||||
};
|
||||
|
||||
let title = match group.get("title") {
|
||||
Some(title) => match title.as_str() {
|
||||
Some(title) => title.to_string(),
|
||||
None => anyhow::bail!("Wrong components index structure: wine group's title entry must be a string")
|
||||
}
|
||||
|
||||
None => anyhow::bail!("Wrong components index structure: wine group's title not found")
|
||||
};
|
||||
|
||||
let versions = serde_json::from_str::<serde_json::Value>(&std::fs::read_to_string(self.folder.join("wine").join(format!("{name}.json")))?)?;
|
||||
|
||||
let mut wine_versions = Vec::new();
|
||||
|
||||
match versions.as_array() {
|
||||
Some(versions) => {
|
||||
for version in versions {
|
||||
wine_versions.push(serde_json::from_value::<wine::Version>(version.to_owned())?);
|
||||
}
|
||||
}
|
||||
|
||||
None => anyhow::bail!("Wrong components index structure: wine versions must be a list")
|
||||
}
|
||||
|
||||
wine_groups.push(wine::Group {
|
||||
name,
|
||||
title,
|
||||
versions: wine_versions
|
||||
});
|
||||
}
|
||||
|
||||
Ok(wine_groups)
|
||||
}
|
||||
|
||||
None => anyhow::bail!("Wrong components index structure: wine entry must be a list")
|
||||
}
|
||||
|
||||
None => anyhow::bail!("Wrong components index structure: wine entry not found")
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to get dxvk versions from components index
|
||||
#[tracing::instrument(level = "debug", ret)]
|
||||
pub fn get_dxvk_versions(&self) -> anyhow::Result<Vec<dxvk::Group>> {
|
||||
tracing::debug!("Getting dxvk versions");
|
||||
|
||||
let components = serde_json::from_str::<serde_json::Value>(&std::fs::read_to_string(self.folder.join("components.json"))?)?;
|
||||
|
||||
match components.get("dxvk") {
|
||||
Some(dxvk) => match dxvk.as_array() {
|
||||
Some(groups) => {
|
||||
let mut dxvk_groups = Vec::with_capacity(groups.len());
|
||||
|
||||
for group in groups {
|
||||
let name = match group.get("name") {
|
||||
Some(name) => match name.as_str() {
|
||||
Some(name) => name.to_string(),
|
||||
None => anyhow::bail!("Wrong components index structure: dxvk group's name entry must be a string")
|
||||
}
|
||||
|
||||
None => anyhow::bail!("Wrong components index structure: dxvk group's name not found")
|
||||
};
|
||||
|
||||
let title = match group.get("title") {
|
||||
Some(title) => match title.as_str() {
|
||||
Some(title) => title.to_string(),
|
||||
None => anyhow::bail!("Wrong components index structure: dxvk group's title entry must be a string")
|
||||
}
|
||||
|
||||
None => anyhow::bail!("Wrong components index structure: dxvk group's title not found")
|
||||
};
|
||||
|
||||
let versions = serde_json::from_str::<serde_json::Value>(&std::fs::read_to_string(self.folder.join("dxvk").join(format!("{name}.json")))?)?;
|
||||
|
||||
let mut dxvk_versions = Vec::new();
|
||||
|
||||
match versions.as_array() {
|
||||
Some(versions) => {
|
||||
for version in versions {
|
||||
dxvk_versions.push(serde_json::from_value::<dxvk::Version>(version.to_owned())?);
|
||||
}
|
||||
}
|
||||
|
||||
None => anyhow::bail!("Wrong components index structure: wine versions must be a list")
|
||||
}
|
||||
|
||||
dxvk_groups.push(dxvk::Group {
|
||||
name,
|
||||
title,
|
||||
versions: dxvk_versions
|
||||
});
|
||||
}
|
||||
|
||||
Ok(dxvk_groups)
|
||||
}
|
||||
|
||||
None => anyhow::bail!("Wrong components index structure: wine entry must be a list")
|
||||
}
|
||||
|
||||
None => anyhow::bail!("Wrong components index structure: wine entry not found")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,30 +3,12 @@ use std::path::PathBuf;
|
|||
use serde::{Serialize, Deserialize};
|
||||
use wincompatlib::prelude::*;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref GROUPS: Vec<Group> = vec![
|
||||
Group {
|
||||
name: String::from("Wine-GE-Proton"),
|
||||
versions: serde_json::from_str::<Vec<Version>>(include_str!("../../components/wine/wine-ge-proton.json")).unwrap().into_iter().take(12).collect()
|
||||
},
|
||||
Group {
|
||||
name: String::from("GE-Proton"),
|
||||
versions: serde_json::from_str::<Vec<Version>>(include_str!("../../components/wine/ge-proton.json")).unwrap().into_iter().take(12).collect()
|
||||
},
|
||||
Group {
|
||||
name: String::from("Soda"),
|
||||
versions: serde_json::from_str::<Vec<Version>>(include_str!("../../components/wine/soda.json")).unwrap().into_iter().take(12).collect()
|
||||
},
|
||||
Group {
|
||||
name: String::from("Lutris"),
|
||||
versions: serde_json::from_str::<Vec<Version>>(include_str!("../../components/wine/lutris.json")).unwrap().into_iter().take(12).collect()
|
||||
}
|
||||
];
|
||||
}
|
||||
use super::loader::ComponentsLoader;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct Group {
|
||||
pub name: String,
|
||||
pub title: String,
|
||||
pub versions: Vec<Version>
|
||||
}
|
||||
|
||||
|
@ -35,20 +17,27 @@ pub struct Version {
|
|||
pub name: String,
|
||||
pub title: String,
|
||||
pub uri: String,
|
||||
pub files: Files,
|
||||
pub recommended: bool
|
||||
pub files: Files
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct Files {
|
||||
pub wine: String,
|
||||
pub wine64: String,
|
||||
pub wineserver: String,
|
||||
pub wineboot: String,
|
||||
pub winecfg: String
|
||||
}
|
||||
|
||||
impl Version {
|
||||
/// Get latest recommended wine version
|
||||
#[inline]
|
||||
pub fn latest() -> Self {
|
||||
get_groups()[0].versions[0].clone()
|
||||
pub fn latest<T: Into<PathBuf>>(components: T) -> anyhow::Result<Self> {
|
||||
Ok(get_groups(components)?[0].versions[0].clone())
|
||||
}
|
||||
|
||||
/// Check is current wine downloaded in specified folder
|
||||
#[inline]
|
||||
pub fn is_downloaded_in<T: Into<PathBuf> + std::fmt::Debug>(&self, folder: T) -> bool {
|
||||
pub fn is_downloaded_in<T: Into<PathBuf>>(&self, folder: T) -> bool {
|
||||
folder.into().join(&self.name).exists()
|
||||
}
|
||||
|
||||
|
@ -70,26 +59,15 @@ impl Version {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct Files {
|
||||
pub wine: String,
|
||||
pub wine64: String,
|
||||
pub wineserver: String,
|
||||
pub wineboot: String,
|
||||
pub winecfg: String
|
||||
}
|
||||
|
||||
/// Get wine groups
|
||||
#[inline]
|
||||
pub fn get_groups() -> Vec<Group> {
|
||||
GROUPS.clone()
|
||||
pub fn get_groups<T: Into<PathBuf>>(components: T) -> anyhow::Result<Vec<Group>> {
|
||||
ComponentsLoader::new(components).get_wine_versions()
|
||||
}
|
||||
|
||||
/// List downloaded wine versions in some specific folder
|
||||
pub fn get_downloaded<T: Into<PathBuf> + std::fmt::Debug>(folder: T) -> std::io::Result<Vec<Version>> {
|
||||
pub fn get_downloaded<T: Into<PathBuf>>(components: T, folder: T) -> anyhow::Result<Vec<Version>> {
|
||||
let mut downloaded = Vec::new();
|
||||
|
||||
let list = get_groups()
|
||||
let list = get_groups(components)?
|
||||
.into_iter()
|
||||
.flat_map(|group| group.versions)
|
||||
.collect::<Vec<Version>>();
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::io::Write;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::Path;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
|
@ -198,33 +197,16 @@ use crate::components::dxvk::{self, Version as DxvkVersion};
|
|||
|
||||
#[cfg(feature = "components")]
|
||||
impl Config {
|
||||
pub fn try_get_selected_wine_info(&self) -> Option<WineVersion> {
|
||||
pub fn try_get_selected_wine_info(&self) -> anyhow::Result<Option<WineVersion>> {
|
||||
match &self.game.wine.selected {
|
||||
Some(selected) => {
|
||||
wine::get_groups()
|
||||
Ok(wine::get_groups(&self.components.path)?
|
||||
.iter()
|
||||
.flat_map(|group| group.versions.clone())
|
||||
.find(|version| version.name.eq(selected))
|
||||
},
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to get a path to the wine64 executable based on `game.wine.builds` and `game.wine.selected`
|
||||
///
|
||||
/// Returns `Some("wine64")` if:
|
||||
/// 1) `game.wine.selected = None`
|
||||
/// 2) wine64 installed and available in system
|
||||
pub fn try_get_wine_executable(&self) -> Option<PathBuf> {
|
||||
match self.try_get_selected_wine_info() {
|
||||
Some(selected) => Some(self.game.wine.builds.join(selected.name).join(selected.files.wine64)),
|
||||
None => {
|
||||
if crate::is_available("wine64") {
|
||||
Some(PathBuf::from("wine64"))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
.find(|version| version.name.eq(selected)))
|
||||
}
|
||||
|
||||
None => Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,16 +216,17 @@ impl Config {
|
|||
/// 1) `Ok(Some(..))` if version was found
|
||||
/// 2) `Ok(None)` if version wasn't found, so too old or dxvk is not applied
|
||||
/// 3) `Err(..)` if failed to get applied dxvk version, likely because wrong prefix path specified
|
||||
pub fn try_get_selected_dxvk_info(&self) -> std::io::Result<Option<DxvkVersion>> {
|
||||
Ok(match wincompatlib::dxvk::Dxvk::get_version(&self.game.wine.prefix)? {
|
||||
pub fn try_get_selected_dxvk_info(&self) -> anyhow::Result<Option<DxvkVersion>> {
|
||||
match wincompatlib::dxvk::Dxvk::get_version(&self.game.wine.prefix)? {
|
||||
Some(version) => {
|
||||
dxvk::get_groups()
|
||||
Ok(dxvk::get_groups(&self.components.path)?
|
||||
.iter()
|
||||
.flat_map(|group| group.versions.clone())
|
||||
.find(move |dxvk| dxvk.version == version)
|
||||
},
|
||||
None => None
|
||||
})
|
||||
.find(move |dxvk| dxvk.version == version))
|
||||
}
|
||||
|
||||
None => Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,9 +24,8 @@ pub fn run() -> anyhow::Result<()> {
|
|||
return Err(anyhow::anyhow!("Game is not installed"));
|
||||
}
|
||||
|
||||
let wine_executable = match config.try_get_wine_executable() {
|
||||
Some(path) => path,
|
||||
None => return Err(anyhow::anyhow!("Couldn't find wine executable"))
|
||||
let Some(wine) = config.try_get_selected_wine_info()? else {
|
||||
anyhow::bail!("Couldn't find wine executable");
|
||||
};
|
||||
|
||||
// Check telemetry servers
|
||||
|
@ -87,7 +86,7 @@ pub fn run() -> anyhow::Result<()> {
|
|||
bash_chain += "gamemoderun ";
|
||||
}
|
||||
|
||||
bash_chain += &format!("'{}' ", wine_executable.to_string_lossy());
|
||||
bash_chain += &format!("'{}' ", wine.files.wine64);
|
||||
|
||||
if let Some(virtual_desktop) = config.game.wine.virtual_desktop.get_command() {
|
||||
bash_chain += &format!("{virtual_desktop} ");
|
||||
|
|
|
@ -148,7 +148,7 @@ impl LauncherState {
|
|||
// Check wine existence
|
||||
#[cfg(feature = "components")]
|
||||
{
|
||||
if config.try_get_wine_executable().is_none() {
|
||||
if config.try_get_selected_wine_info()?.is_none() {
|
||||
return Ok(Self::WineNotInstalled);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue