Changed config file format and struture

- added `Config::try_get_wine_executable` method
- fixed launher freezing when running the game
This commit is contained in:
Observer KRypt0n_ 2022-07-01 12:20:08 +02:00
parent 1eed56e53a
commit 8bec171c5d
No known key found for this signature in database
GPG key ID: 844DA47BA25FE1E2
4 changed files with 139 additions and 32 deletions

View file

@ -14,6 +14,6 @@ libadwaita = "0.1"
anime-game-core = { path = "anime-game-core", features = ["all"] }
serde = { version = "1.0", features = ["derive"] }
toml = "0.5.9"
serde_json = "1.0"
dirs = "4.0.0"

View file

@ -5,7 +5,7 @@ use std::io::{Error, ErrorKind, Write};
use serde::{Serialize, Deserialize};
use super::consts::config_file;
use super::consts::*;
pub fn get() -> Result<Config, Error> {
match config_file() {
@ -13,13 +13,13 @@ pub fn get() -> Result<Config, Error> {
// Try to read config if the file exists
if Path::new(&path).exists() {
let mut file = File::open(path)?;
let mut toml = String::new();
let mut json = String::new();
file.read_to_string(&mut toml)?;
file.read_to_string(&mut json)?;
match toml::from_str::<Config>(&toml) {
Ok(toml) => Ok(toml),
Err(err) => Err(Error::new(ErrorKind::InvalidData, format!("Failed to decode data from toml format: {}", err.to_string())))
match serde_json::from_str::<Config>(&json) {
Ok(json) => Ok(json),
Err(err) => Err(Error::new(ErrorKind::InvalidData, format!("Failed to decode data from json format: {}", err.to_string())))
}
}
@ -39,13 +39,13 @@ pub fn update(config: Config) -> Result<(), Error> {
Some(path) => {
let mut file = File::create(&path)?;
match toml::to_string(&config) {
Ok(toml) => {
file.write_all(&mut toml.as_bytes())?;
match serde_json::to_string_pretty(&config) {
Ok(json) => {
file.write_all(&mut json.as_bytes())?;
Ok(())
},
Err(err) => Err(Error::new(ErrorKind::InvalidData, format!("Failed to encode data into toml format: {}", err.to_string())))
Err(err) => Err(Error::new(ErrorKind::InvalidData, format!("Failed to encode data into json format: {}", err.to_string())))
}
},
None => Err(Error::new(ErrorKind::NotFound, format!("Failed to get config file path")))
@ -54,35 +54,137 @@ pub fn update(config: Config) -> Result<(), Error> {
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Config {
pub paths: Paths,
pub patch: Patch,
pub wine: Wine
pub launcher: Launcher,
pub game: Game,
pub patch: Patch
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Paths {
pub game: String,
pub patch: String
impl Config {
/// Try to get a path to the wine executable based on `game.wine.builds` and `game.wine.selected`
pub fn try_get_wine_executable(&self) -> Option<String> {
match &self.game.wine.selected {
Some(selected) => {
// Most of wine builds
let path = format!("{}/{}/bin/wine", &self.game.wine.builds, &selected);
if Path::new(&path).exists() {
return Some(path);
}
// Proton-based builds
let path = format!("{}/{}/files/bin/wine", &self.game.wine.builds, &selected);
if Path::new(&path).exists() {
return Some(path);
}
// ????
None
},
None => None
}
}
}
#[derive(Debug, Serialize, Deserialize, Default)]
#[derive(Debug, Serialize, Deserialize)]
pub struct Launcher {
pub language: String
}
impl Default for Launcher {
fn default() -> Self {
Self {
language: String::from("en-us")
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Patch {
pub hosts: Vec<String>
pub path: String,
pub servers: Vec<String>
}
impl Default for Patch {
fn default() -> Self {
Self {
path: match launcher_dir() {
Some(dir) => format!("{}/patch", dir),
None => String::new()
},
servers: Vec::new()
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Game {
pub path: String,
pub voices: Vec<String>,
pub wine: Wine,
pub enhancements: Enhancements,
pub environment: HashMap<String, String>
}
impl Default for Game {
fn default() -> Self {
Self {
path: match launcher_dir() {
Some(dir) => format!("{}/game/drive_c/Program Files/Genshin Impact", dir),
None => String::new()
},
voices: vec![
String::from("en-us")
],
wine: Wine::default(),
enhancements: Enhancements::default(),
environment: HashMap::new()
}
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Wine {
pub prefix: String,
pub executable: String,
pub environment: HashMap<String, String>
pub builds: String,
pub selected: Option<String>,
pub sync: String
}
impl Default for Wine {
fn default() -> Self {
Self {
prefix: String::new(),
executable: String::new(),
environment: HashMap::new()
prefix: match launcher_dir() {
Some(dir) => format!("{}/game", dir),
None => String::new()
},
builds: match launcher_dir() {
Some(dir) => format!("{}/runners", dir),
None => String::new()
},
selected: None,
sync: String::from("esync")
}
}
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct Enhancements {
pub fsr: Fsr,
pub gamemode: bool
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Fsr {
pub strength: u8,
pub enabled: bool
}
impl Default for Fsr {
fn default() -> Self {
Self {
strength: 3,
enabled: false
}
}
}

View file

@ -25,7 +25,7 @@ pub fn config_file() -> Option<String> {
Some(value) => value.clone(),
None => {
let value = match launcher_dir() {
Some(dir) => Some(format!("{}/config.toml", dir)),
Some(dir) => Some(format!("{}/config.json", dir)),
None => None
};

View file

@ -7,16 +7,21 @@ use super::config;
pub fn run() -> Result<(), Error> {
let config = config::get()?;
if Path::new(&config.paths.game).exists() {
if !Path::new(&config.game.path).exists() {
return Err(Error::new(ErrorKind::Other, "Game is not installed"));
}
Command::new(config.wine.executable)
.env("WINEPREFIX", &config.wine.prefix)
.envs(config.wine.environment)
.current_dir(config.paths.game)
let wine_executable = match config.try_get_wine_executable() {
Some(path) => path,
None => return Err(Error::new(ErrorKind::Other, "Couldn't find wine executable"))
};
Command::new(wine_executable)
.env("WINEPREFIX", config.game.wine.prefix)
.envs(config.game.environment)
.current_dir(config.game.path)
.arg("launcher.bat")
.output()?;
.spawn()?;
Ok(())
}