mirror of
https://github.com/djibux/BoilR.git
synced 2026-09-01 05:53:41 +02:00
@@ -26,7 +26,7 @@ Optionally you can set BoilR up to automatically download artwork from [SteamGri
|
|||||||
- [x] [UPlay](https://ubisoftconnect.com)
|
- [x] [UPlay](https://ubisoftconnect.com)
|
||||||
- [x] [Lutris](https://github.com/lutris/lutris)
|
- [x] [Lutris](https://github.com/lutris/lutris)
|
||||||
- [x] [Legendary](https://github.com/derrod/legendary)
|
- [x] [Legendary](https://github.com/derrod/legendary)
|
||||||
- [x] [Heroic Launcher](https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher) (Only Epic Games for now)
|
- [x] [Heroic Launcher](https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher) (Only Linux & Epic Games for now)
|
||||||
- [ ] XBox/Microsoft Store integration
|
- [ ] XBox/Microsoft Store integration
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -42,4 +42,11 @@ impl Platform<ManifestItem, EpicGamesManifestsError> for EpicPlatform {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn needs_proton(&self, _input: &ManifestItem) -> bool {
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
return true;
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ pub(crate) struct PlayTask {
|
|||||||
pub working_dir: Option<String>,
|
pub working_dir: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub(crate) struct GogShortcut {
|
pub(crate) struct GogShortcut {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub game_folder: String,
|
pub game_folder: String,
|
||||||
|
|||||||
@@ -149,6 +149,13 @@ impl Platform<GogShortcut, GogErrors> for GogPlatform {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn needs_proton(&self, _input: &GogShortcut) -> bool {
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
return true;
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
|
|||||||
+19
-20
@@ -1,43 +1,42 @@
|
|||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use steam_shortcuts_util::{shortcut::ShortcutOwned, Shortcut};
|
use steam_shortcuts_util::{shortcut::ShortcutOwned, Shortcut};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct HeroicGame {
|
pub struct HeroicGame {
|
||||||
pub app_name: String,
|
pub app_name: String,
|
||||||
pub can_run_offline: bool,
|
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub is_dlc: bool,
|
pub is_dlc: bool,
|
||||||
pub install_path: String,
|
pub install_path: String,
|
||||||
pub executable: String,
|
pub executable: String,
|
||||||
pub config_folder: Option<String>,
|
pub launch_parameters: String,
|
||||||
pub legendary_location: Option<String>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<HeroicGame> for ShortcutOwned {
|
impl From<HeroicGame> for ShortcutOwned {
|
||||||
fn from(game: HeroicGame) -> Self {
|
fn from(game: HeroicGame) -> Self {
|
||||||
|
let target_path = Path::new(&game.install_path).join(game.executable);
|
||||||
let legendary = game.legendary_location.unwrap_or("legendary".to_string());
|
|
||||||
|
|
||||||
let icon = format!("\"{}\\{}\"", game.install_path, game.executable);
|
|
||||||
let launch = match game.config_folder{
|
|
||||||
Some(config_folder) => {
|
|
||||||
format!("env XDG_CONFIG_HOME={} {}", config_folder, legendary)
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
format!("{}", legendary)
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let launch_options = format!("launch {}",game.app_name);
|
|
||||||
|
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
let mut target = target_path.to_string_lossy().to_string();
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
{
|
||||||
|
if !target.starts_with("\"") && !target.ends_with("\"") {
|
||||||
|
target = format!("\"{}\"", target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let target = target_path.to_string_lossy().to_string();
|
||||||
|
|
||||||
let shortcut = Shortcut::new(
|
let shortcut = Shortcut::new(
|
||||||
"0",
|
"0",
|
||||||
game.title.as_str(),
|
game.title.as_str(),
|
||||||
launch.as_str(),
|
&target,
|
||||||
"",
|
"",
|
||||||
icon.as_str(),
|
|
||||||
"",
|
"",
|
||||||
&launch_options.as_str()
|
"",
|
||||||
|
&game.launch_parameters.as_str(),
|
||||||
);
|
);
|
||||||
let mut owned_shortcut = shortcut.to_owned();
|
let mut owned_shortcut = shortcut.to_owned();
|
||||||
owned_shortcut.tags.push("Heroic".to_owned());
|
owned_shortcut.tags.push("Heroic".to_owned());
|
||||||
|
|||||||
+33
-114
@@ -1,128 +1,51 @@
|
|||||||
use super::{HeroicGame, HeroicSettings};
|
use super::{HeroicGame, HeroicSettings};
|
||||||
use crate::platform::{Platform, SettingsValidity};
|
use crate::platform::{Platform, SettingsValidity};
|
||||||
use serde_json::from_str;
|
use std::collections::HashMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::Command;
|
|
||||||
|
|
||||||
pub struct HeroicPlatform {
|
pub struct HeroicPlatform {
|
||||||
pub settings: HeroicSettings,
|
pub settings: HeroicSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
|
||||||
enum InstallationMode {
|
enum InstallationMode {
|
||||||
FlatPak,
|
FlatPak,
|
||||||
UserBin,
|
UserBin,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
fn get_installed_json_location(install_mode: &InstallationMode) -> PathBuf {
|
||||||
fn get_legendary_location(install_mode: &InstallationMode) -> &'static str {
|
let home_dir = std::env::var("HOME").unwrap_or("".to_string());
|
||||||
match install_mode{
|
|
||||||
InstallationMode::FlatPak => "/var/lib/flatpak/app/com.heroicgameslauncher.hgl/current/active/files/bin/heroic/resources/app.asar.unpacked/build/bin/linux/legendary",
|
|
||||||
InstallationMode::UserBin => "/opt/Heroic/resources/app.asar.unpacked/build/bin/linux/legendary"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
|
||||||
fn get_config_folder(install_mode: &InstallationMode) -> Option<String> {
|
|
||||||
match install_mode {
|
match install_mode {
|
||||||
InstallationMode::FlatPak => {
|
InstallationMode::FlatPak => Path::new(&home_dir)
|
||||||
let home_dir = std::env::var("HOME").unwrap_or("".to_string());
|
.join(".var/app/com.heroicgameslauncher.hgl/config/legendary/installed.json"),
|
||||||
Some(
|
InstallationMode::UserBin => Path::new(&home_dir).join(".config/legendary/installed.json"),
|
||||||
Path::new(&home_dir)
|
|
||||||
.join(".var/app/com.heroicgameslauncher.hgl/config")
|
|
||||||
.to_string_lossy()
|
|
||||||
.to_string(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
InstallationMode::UserBin => None,
|
|
||||||
}
|
}
|
||||||
|
.to_path_buf()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
fn find_legendary_location() -> Option<String> {
|
|
||||||
match heroic_folder_from_registry().or_else(heroic_folder_from_appdata) {
|
|
||||||
Some(heroic_folder) => {
|
|
||||||
let legendary_path = heroic_folder
|
|
||||||
.join("resources\\app.asar.unpacked\\build\\bin\\win32\\legendary.exe");
|
|
||||||
if legendary_path.exists() {
|
|
||||||
Some(legendary_path.to_path_buf().to_string_lossy().to_string())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
fn heroic_folder_from_registry() -> Option<PathBuf> {
|
|
||||||
use winreg::enums::*;
|
|
||||||
use winreg::RegKey;
|
|
||||||
|
|
||||||
let hklm = RegKey::predef(HKEY_CURRENT_USER);
|
|
||||||
if let Ok(launcher) = hklm.open_subkey("Software\\035fb1f9-7381-565b-92bb-ed6b2a3b99ba") {
|
|
||||||
let path_string: Result<String, _> = launcher.get_value("InstallLocation");
|
|
||||||
if let Ok(path_string) = path_string {
|
|
||||||
//.join("resources/app.asar.unpacked/build/bin/win32/legendary.exe")
|
|
||||||
let path = Path::new(&path_string);
|
|
||||||
if path.exists() {
|
|
||||||
return Some(path.to_path_buf());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
fn heroic_folder_from_appdata() -> Option<PathBuf> {
|
|
||||||
let key = "APPDATA";
|
|
||||||
match std::env::var(key) {
|
|
||||||
Ok(program_data) => {
|
|
||||||
let path = Path::new(&program_data).join("heroic");
|
|
||||||
if path.exists() {
|
|
||||||
Some(path.to_path_buf())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(_err) => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
|
||||||
fn get_shortcuts_from_install_mode(
|
fn get_shortcuts_from_install_mode(
|
||||||
install_mode: &InstallationMode,
|
install_mode: &InstallationMode,
|
||||||
) -> Result<Vec<HeroicGame>, Box<dyn Error>> {
|
) -> Result<Vec<HeroicGame>, Box<dyn Error>> {
|
||||||
let legendary = get_legendary_location(install_mode);
|
let installed_path = get_installed_json_location(install_mode);
|
||||||
let config_folder = get_config_folder(install_mode);
|
get_shortcuts_from_location(installed_path)
|
||||||
get_shortcuts_from_location(config_folder, legendary.to_string())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_shortcuts_from_location(
|
fn get_shortcuts_from_location<P: AsRef<Path>>(path: P) -> Result<Vec<HeroicGame>, Box<dyn Error>> {
|
||||||
config_folder: Option<String>,
|
let installed_json_path = path.as_ref();
|
||||||
legendary: String,
|
if installed_json_path.exists() {
|
||||||
) -> Result<Vec<HeroicGame>, Box<dyn Error>> {
|
let json = std::fs::read_to_string(installed_json_path)?;
|
||||||
let output = if let Some(config_folder) = config_folder.clone() {
|
let games_map = serde_json::from_str::<HashMap<String, HeroicGame>>(&json)?;
|
||||||
Command::new(&legendary)
|
let mut games = vec![];
|
||||||
.env("XDG_CONFIG_HOME", config_folder)
|
for game in games_map.values() {
|
||||||
.arg("list-installed")
|
games.push(game.clone());
|
||||||
.arg("--json")
|
}
|
||||||
.output()?
|
return Ok(games);
|
||||||
} else {
|
}
|
||||||
Command::new(&legendary)
|
return Ok(vec![]);
|
||||||
.arg("list-installed")
|
|
||||||
.arg("--json")
|
|
||||||
.output()?
|
|
||||||
};
|
|
||||||
let json = String::from_utf8_lossy(&output.stdout);
|
|
||||||
let mut legendary_ouput: Vec<HeroicGame> = from_str(&json)?;
|
|
||||||
legendary_ouput.iter_mut().for_each(|mut game| {
|
|
||||||
game.config_folder = config_folder.clone();
|
|
||||||
game.legendary_location = Some(legendary.to_string());
|
|
||||||
});
|
|
||||||
Ok(legendary_ouput)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Platform<HeroicGame, Box<dyn Error>> for HeroicPlatform {
|
impl Platform<HeroicGame, Box<dyn Error>> for HeroicPlatform {
|
||||||
@@ -133,22 +56,14 @@ impl Platform<HeroicGame, Box<dyn Error>> for HeroicPlatform {
|
|||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"Heroic"
|
"Heroic"
|
||||||
}
|
}
|
||||||
#[cfg(target_family = "unix")]
|
fn get_shortcuts(&self) -> Result<Vec<HeroicGame>, Box<dyn Error>> {
|
||||||
fn get_shortcuts(&self) -> Result<Vec<HeroicGame>, Box<dyn Error>> {
|
|
||||||
let install_modes = vec![InstallationMode::FlatPak, InstallationMode::UserBin];
|
let install_modes = vec![InstallationMode::FlatPak, InstallationMode::UserBin];
|
||||||
let first_working_instal = install_modes
|
let shortcuts = install_modes
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|install_mode| get_shortcuts_from_install_mode(install_mode).ok());
|
.filter_map(|install_mode| get_shortcuts_from_install_mode(install_mode).ok())
|
||||||
match first_working_instal {
|
.flatten()
|
||||||
Some(res) => return Ok(res),
|
.collect();
|
||||||
None => get_shortcuts_from_install_mode(&install_modes[0]),
|
Ok(shortcuts)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
fn get_shortcuts(&self) -> Result<Vec<HeroicGame>, Box<dyn Error>> {
|
|
||||||
let legendary = find_legendary_location().unwrap_or("legendary".to_string());
|
|
||||||
get_shortcuts_from_location(None, legendary)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
@@ -165,4 +80,8 @@ impl Platform<HeroicGame, Box<dyn Error>> for HeroicPlatform {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn needs_proton(&self, _input: &HeroicGame) -> bool {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ mod heroic_game;
|
|||||||
mod heroic_platform;
|
mod heroic_platform;
|
||||||
mod settings;
|
mod settings;
|
||||||
|
|
||||||
|
|
||||||
pub use heroic_game::*;
|
pub use heroic_game::*;
|
||||||
pub use heroic_platform::*;
|
pub use heroic_platform::*;
|
||||||
pub use settings::*;
|
pub use settings::*;
|
||||||
|
|||||||
@@ -51,10 +51,7 @@ impl Platform<ItchGame, ItchErrors> for ItchPlatform {
|
|||||||
|
|
||||||
//This is done to paths dedupe
|
//This is done to paths dedupe
|
||||||
let paths: HashSet<&DbPaths> = paths.iter().collect();
|
let paths: HashSet<&DbPaths> = paths.iter().collect();
|
||||||
let res = paths
|
let res = paths.iter().filter_map(|e| dbpath_to_game(*e)).collect();
|
||||||
.iter()
|
|
||||||
.filter_map(|e| dbpath_to_game(*e))
|
|
||||||
.collect();
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +69,16 @@ impl Platform<ItchGame, ItchErrors> for ItchPlatform {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn needs_proton(&self, _input: &ItchGame) -> bool {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
fn needs_proton(&self, input: &ItchGame) -> bool {
|
||||||
|
//We can only really guess here
|
||||||
|
return input.executable.ends_with("exe");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dbpath_to_game(paths: &DbPaths) -> Option<ItchGame> {
|
fn dbpath_to_game(paths: &DbPaths) -> Option<ItchGame> {
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ impl Platform<LegendaryGame, Box<dyn Error>> for LegendaryPlatform {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn needs_proton(&self, _input: &LegendaryGame) -> bool {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_legendary_command(program: &str) -> Result<Vec<LegendaryGame>, Box<dyn Error>> {
|
fn execute_legendary_command(program: &str) -> Result<Vec<LegendaryGame>, Box<dyn Error>> {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ pub struct LutrisPlatform {
|
|||||||
pub settings: LutrisSettings,
|
pub settings: LutrisSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Platform<LutrisGame, Box<dyn Error>> for LutrisPlatform {
|
impl Platform<LutrisGame, Box<dyn Error>> for LutrisPlatform {
|
||||||
fn enabled(&self) -> bool {
|
fn enabled(&self) -> bool {
|
||||||
self.settings.enabled
|
self.settings.enabled
|
||||||
@@ -21,10 +20,14 @@ impl Platform<LutrisGame, Box<dyn Error>> for LutrisPlatform {
|
|||||||
|
|
||||||
fn get_shortcuts(&self) -> Result<Vec<LutrisGame>, Box<dyn Error>> {
|
fn get_shortcuts(&self) -> Result<Vec<LutrisGame>, Box<dyn Error>> {
|
||||||
let default_lutris_exe = "lutris".to_string();
|
let default_lutris_exe = "lutris".to_string();
|
||||||
let lutris_executable = self.settings.executable.as_ref().unwrap_or(&default_lutris_exe);
|
let lutris_executable = self
|
||||||
|
.settings
|
||||||
|
.executable
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&default_lutris_exe);
|
||||||
let lutris_command = Command::new(lutris_executable).arg("-lo").output()?;
|
let lutris_command = Command::new(lutris_executable).arg("-lo").output()?;
|
||||||
let output = String::from_utf8_lossy(&lutris_command.stdout).to_string();
|
let output = String::from_utf8_lossy(&lutris_command.stdout).to_string();
|
||||||
let games = parse_lutris_games(output.as_str());
|
let games = parse_lutris_games(output.as_str());
|
||||||
let mut res = vec![];
|
let mut res = vec![];
|
||||||
for game in games {
|
for game in games {
|
||||||
if game.platform != "steam" {
|
if game.platform != "steam" {
|
||||||
@@ -48,4 +51,8 @@ impl Platform<LutrisGame, Box<dyn Error>> for LutrisPlatform {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn needs_proton(&self, _input: &LutrisGame) -> bool {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
use steam_shortcuts_util::{shortcut::ShortcutOwned, Shortcut};
|
use steam_shortcuts_util::{shortcut::ShortcutOwned, Shortcut};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct OriginGame {
|
pub struct OriginGame {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
|
|||||||
@@ -75,6 +75,16 @@ impl Platform<OriginGame, OriginErrors> for OriginPlatform {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn needs_proton(&self, _input: &OriginGame) -> bool {
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
return false;
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
{
|
||||||
|
//TODO Update this when origin gets support on linux
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_folder_mfst_file_content(game_folder_path: &Path) -> Option<String> {
|
fn get_folder_mfst_file_content(game_folder_path: &Path) -> Option<String> {
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ where
|
|||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
fn create_symlinks(&self) -> bool;
|
fn create_symlinks(&self) -> bool;
|
||||||
|
|
||||||
|
// HOME/.local/share/Steam/config/config.vdf
|
||||||
|
fn needs_proton(&self, input: &T) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum SettingsValidity {
|
pub enum SettingsValidity {
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ fn get_vdf_path<S: AsRef<str>>(steamid: S) -> Option<PathBuf> {
|
|||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Err(e) => return None,
|
Err(_e) => return None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +299,7 @@ fn get_level_db_location() -> Option<PathBuf> {
|
|||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Err(e) => return None,
|
Err(_e) => return None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
mod settings;
|
mod settings;
|
||||||
mod utils;
|
mod utils;
|
||||||
mod collections;
|
mod collections;
|
||||||
|
mod proton_vdf_util;
|
||||||
|
|
||||||
|
|
||||||
pub use settings::SteamSettings;
|
pub use settings::SteamSettings;
|
||||||
pub use utils::*;
|
pub use utils::*;
|
||||||
pub use collections::*;
|
pub use collections::*;
|
||||||
|
pub use proton_vdf_util::*;
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
="X"
|
||||||
|
={
|
||||||
|
+"name" "proton_experimental"
|
||||||
|
+"config" ""
|
||||||
|
+"Priority" "250"
|
||||||
|
=}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use nom::FindSubstring;
|
||||||
|
|
||||||
|
|
||||||
|
pub fn setup_proton_games<B: AsRef<str>>(games: &[B]){
|
||||||
|
if let Ok(home) = std::env::var("HOME"){
|
||||||
|
let config_file = Path::new(&home).join(".local/share/Steam/config/config.vdf");
|
||||||
|
if config_file.exists(){
|
||||||
|
if let Ok(config_content) = std::fs::read_to_string(&config_file){
|
||||||
|
let new_string = enable_proton_games(config_content, games);
|
||||||
|
std::fs::write(config_file, new_string).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enable_proton_games<S: AsRef<str>, B: AsRef<str>>(vdf_content: S, games: &[B]) -> String {
|
||||||
|
let vdf_content = vdf_content.as_ref();
|
||||||
|
if let Some(section_info) = find_indexes(vdf_content) {
|
||||||
|
let (base_indent_string, field_indent_string) = {
|
||||||
|
let mut a = String::new();
|
||||||
|
let mut b = String::new();
|
||||||
|
for _i in 0..=section_info.base_indentation {
|
||||||
|
a.push('\t');
|
||||||
|
b.push('\t');
|
||||||
|
}
|
||||||
|
b.push('\t');
|
||||||
|
(a, b)
|
||||||
|
};
|
||||||
|
|
||||||
|
let proton_replace_string = include_str!("proton_string.txt");
|
||||||
|
let section_str = &vdf_content[section_info.start..section_info.append_end];
|
||||||
|
let games_strings_to_add = games
|
||||||
|
.iter()
|
||||||
|
.filter(|g| {
|
||||||
|
let game_section_start = format!("\"{}\"\n", g.as_ref());
|
||||||
|
!section_str.contains(&game_section_start)
|
||||||
|
})
|
||||||
|
.map(|game_id| {
|
||||||
|
let res = proton_replace_string.to_string();
|
||||||
|
let res = res.replace("\"X\"", &format!("\"{}\"", game_id.as_ref()));
|
||||||
|
let res = res.replace("=", &base_indent_string);
|
||||||
|
let res = res.replace("+", &field_indent_string);
|
||||||
|
res
|
||||||
|
});
|
||||||
|
let mut new_section = section_str.to_string();
|
||||||
|
for game_string in games_strings_to_add {
|
||||||
|
new_section.push_str(&game_string);
|
||||||
|
}
|
||||||
|
new_section.push_str(§ion_info.end_key);
|
||||||
|
|
||||||
|
let before_section = &vdf_content[..section_info.start];
|
||||||
|
let after_section = &vdf_content[section_info.end..];
|
||||||
|
return format!("{}{}{}", before_section, new_section, after_section);
|
||||||
|
} else {
|
||||||
|
//TODO make this an error instead?
|
||||||
|
println!("Could not find proton section in steam, try to manually set proton on at least one game and then rerun");
|
||||||
|
}
|
||||||
|
return vdf_content.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SectionInfo {
|
||||||
|
start: usize,
|
||||||
|
end: usize,
|
||||||
|
append_end: usize,
|
||||||
|
base_indentation: usize,
|
||||||
|
end_key: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_indexes<S: AsRef<str>>(vdf_content: S) -> Option<SectionInfo> {
|
||||||
|
let compat_key = "\"CompatToolMapping\"\n";
|
||||||
|
let vdf_content = vdf_content.as_ref();
|
||||||
|
if let Some(compat_index) = vdf_content.find_substring(compat_key) {
|
||||||
|
let compat_index = compat_index + compat_key.len();
|
||||||
|
let after_key = vdf_content[compat_index..].to_string();
|
||||||
|
if let Some(base_indentation) = after_key.find('{') {
|
||||||
|
let mut end_key = "\n".to_string();
|
||||||
|
for _i in 0..base_indentation {
|
||||||
|
end_key.push('\t');
|
||||||
|
}
|
||||||
|
end_key.push('}');
|
||||||
|
if let Some(end_index) = after_key.as_str().find_substring(&end_key) {
|
||||||
|
return Some(SectionInfo {
|
||||||
|
start: compat_index,
|
||||||
|
end: compat_index + end_index + end_key.len(),
|
||||||
|
append_end: compat_index + end_index,
|
||||||
|
base_indentation,
|
||||||
|
end_key: end_key.to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn can_find_index_test() {
|
||||||
|
let input = include_str!("../testdata/vdf/testconfig.vdf");
|
||||||
|
let SectionInfo {
|
||||||
|
start,
|
||||||
|
end,
|
||||||
|
base_indentation,
|
||||||
|
..
|
||||||
|
} = find_indexes(input).unwrap();
|
||||||
|
|
||||||
|
let actual = input[start..end].to_string();
|
||||||
|
let expected = include_str!("../testdata/vdf/compatmappingsection.vdf");
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
assert_eq!(4, base_indentation);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn enable_proton_test() {
|
||||||
|
let input = include_str!("../testdata/vdf/testconfig.vdf");
|
||||||
|
let output = enable_proton_games(input, &vec!["42", "43", "44"]);
|
||||||
|
let expected = include_str!("../testdata/vdf/testconfig_expected.vdf");
|
||||||
|
assert_eq!(expected,output );
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn enable_proton_test_empty() {
|
||||||
|
let input = include_str!("../testdata/vdf/testconfig.vdf");
|
||||||
|
let output = enable_proton_games(input, &vec!["2719403116"]);
|
||||||
|
let expected = include_str!("../testdata/vdf/testconfig.vdf");
|
||||||
|
assert_eq!(expected,output );
|
||||||
|
}
|
||||||
|
}
|
||||||
+31
-11
@@ -1,19 +1,22 @@
|
|||||||
use steam_shortcuts_util::{shortcut::ShortcutOwned, shortcuts_to_bytes};
|
use steam_shortcuts_util::{shortcut::ShortcutOwned, shortcuts_to_bytes};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
egs::EpicPlatform,
|
egs::EpicPlatform,
|
||||||
heroic::HeroicPlatform,
|
|
||||||
legendary::LegendaryPlatform,
|
legendary::LegendaryPlatform,
|
||||||
lutris::lutris_platform::LutrisPlatform,
|
lutris::lutris_platform::LutrisPlatform,
|
||||||
platform::Platform,
|
platform::Platform,
|
||||||
settings::Settings,
|
settings::Settings,
|
||||||
steam::{
|
steam::{
|
||||||
get_shortcuts_for_user, get_shortcuts_paths, write_collections, Collection, ShortcutInfo,
|
get_shortcuts_for_user, get_shortcuts_paths, setup_proton_games, write_collections,
|
||||||
SteamUsersInfo,
|
Collection, ShortcutInfo, SteamUsersInfo,
|
||||||
},
|
},
|
||||||
steamgriddb::download_images_for_users,
|
steamgriddb::download_images_for_users,
|
||||||
uplay::Uplay,
|
uplay::Uplay,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
use crate::heroic::HeroicPlatform;
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use crate::{gog::GogPlatform, itch::ItchPlatform, origin::OriginPlatform};
|
use crate::{gog::GogPlatform, itch::ItchPlatform, origin::OriginPlatform};
|
||||||
@@ -29,6 +32,9 @@ pub async fn run_sync(settings: &Settings) -> Result<(), Box<dyn Error>> {
|
|||||||
.iter()
|
.iter()
|
||||||
.flat_map(|s| s.1.clone())
|
.flat_map(|s| s.1.clone())
|
||||||
.collect();
|
.collect();
|
||||||
|
for shortcut in &all_shortcuts {
|
||||||
|
println!("Appid: {} name: {}", shortcut.app_id, shortcut.app_name);
|
||||||
|
}
|
||||||
println!("Found {} user(s)", userinfo_shortcuts.len());
|
println!("Found {} user(s)", userinfo_shortcuts.len());
|
||||||
for user in userinfo_shortcuts.iter_mut() {
|
for user in userinfo_shortcuts.iter_mut() {
|
||||||
let start_time = std::time::Instant::now();
|
let start_time = std::time::Instant::now();
|
||||||
@@ -45,6 +51,7 @@ pub async fn run_sync(settings: &Settings) -> Result<(), Box<dyn Error>> {
|
|||||||
shortcut_info.shortcuts.extend(all_shortcuts.clone());
|
shortcut_info.shortcuts.extend(all_shortcuts.clone());
|
||||||
|
|
||||||
fix_shortcut_icons(user, &mut shortcut_info.shortcuts);
|
fix_shortcut_icons(user, &mut shortcut_info.shortcuts);
|
||||||
|
|
||||||
save_shortcuts(&shortcut_info.shortcuts, Path::new(&shortcut_info.path));
|
save_shortcuts(&shortcut_info.shortcuts, Path::new(&shortcut_info.path));
|
||||||
|
|
||||||
if settings.steam.create_collections {
|
if settings.steam.create_collections {
|
||||||
@@ -121,7 +128,7 @@ fn write_shortcut_collections<S: AsRef<str>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_platform_shortcuts(settings: &Settings) -> Vec<(String, Vec<ShortcutOwned>)> {
|
fn get_platform_shortcuts(settings: &Settings) -> Vec<(String, Vec<ShortcutOwned>)> {
|
||||||
let platform_results = vec![
|
let mut platform_results = vec![
|
||||||
update_platform_shortcuts(&EpicPlatform::new(settings.epic_games.clone())),
|
update_platform_shortcuts(&EpicPlatform::new(settings.epic_games.clone())),
|
||||||
update_platform_shortcuts(&LegendaryPlatform::new(settings.legendary.clone())),
|
update_platform_shortcuts(&LegendaryPlatform::new(settings.legendary.clone())),
|
||||||
update_platform_shortcuts(&ItchPlatform::new(settings.itch.clone())),
|
update_platform_shortcuts(&ItchPlatform::new(settings.itch.clone())),
|
||||||
@@ -137,10 +144,14 @@ fn get_platform_shortcuts(settings: &Settings) -> Vec<(String, Vec<ShortcutOwned
|
|||||||
update_platform_shortcuts(&LutrisPlatform {
|
update_platform_shortcuts(&LutrisPlatform {
|
||||||
settings: settings.lutris.clone(),
|
settings: settings.lutris.clone(),
|
||||||
}),
|
}),
|
||||||
update_platform_shortcuts(&HeroicPlatform {
|
|
||||||
settings: settings.heroic.clone(),
|
|
||||||
}),
|
|
||||||
];
|
];
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
{
|
||||||
|
platform_results.push(update_platform_shortcuts(&HeroicPlatform {
|
||||||
|
settings: settings.heroic.clone(),
|
||||||
|
}));
|
||||||
|
}
|
||||||
platform_results.iter().filter_map(|p| p.clone()).collect()
|
platform_results.iter().filter_map(|p| p.clone()).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,6 +187,7 @@ where
|
|||||||
P: Platform<T, E>,
|
P: Platform<T, E>,
|
||||||
E: std::fmt::Debug + std::fmt::Display,
|
E: std::fmt::Debug + std::fmt::Display,
|
||||||
T: Into<ShortcutOwned>,
|
T: Into<ShortcutOwned>,
|
||||||
|
T: Clone,
|
||||||
{
|
{
|
||||||
if platform.enabled() {
|
if platform.enabled() {
|
||||||
if let crate::platform::SettingsValidity::Invalid { reason } = platform.settings_valid() {
|
if let crate::platform::SettingsValidity::Invalid { reason } = platform.settings_valid() {
|
||||||
@@ -199,12 +211,13 @@ where
|
|||||||
|
|
||||||
match shortcuts_to_add_result {
|
match shortcuts_to_add_result {
|
||||||
Ok(shortcuts_to_add) => {
|
Ok(shortcuts_to_add) => {
|
||||||
|
let mut shortcuts_to_proton = vec![];
|
||||||
let mut shortcuts_to_add_transformed = vec![];
|
let mut shortcuts_to_add_transformed = vec![];
|
||||||
for shortcut in shortcuts_to_add {
|
for shortcut in shortcuts_to_add {
|
||||||
let mut shortcut_owned: ShortcutOwned = shortcut.into();
|
let mut shortcut_owned: ShortcutOwned = shortcut.clone().into();
|
||||||
shortcut_owned.dev_kit_game_id =
|
shortcut_owned.dev_kit_game_id =
|
||||||
format!("{}-{}", BOILR_TAG, shortcut_owned.app_id);
|
format!("{}-{}", BOILR_TAG, shortcut_owned.app_id);
|
||||||
shortcuts_to_add_transformed.push(shortcut_owned);
|
shortcuts_to_add_transformed.push((shortcut, shortcut_owned));
|
||||||
}
|
}
|
||||||
|
|
||||||
let shortcuts_to_add = shortcuts_to_add_transformed;
|
let shortcuts_to_add = shortcuts_to_add_transformed;
|
||||||
@@ -215,15 +228,22 @@ where
|
|||||||
platform.name()
|
platform.name()
|
||||||
);
|
);
|
||||||
|
|
||||||
for shortcut_owned in shortcuts_to_add {
|
for (orign_shortcut, shortcut_owned) in shortcuts_to_add {
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
let shortcut_owned = if platform.create_symlinks() {
|
let shortcut_owned = if platform.create_symlinks() {
|
||||||
crate::sync::symlinks::create_sym_links(&shortcut_owned)
|
crate::sync::symlinks::create_sym_links(&shortcut_owned)
|
||||||
} else {
|
} else {
|
||||||
shortcut_owned
|
shortcut_owned
|
||||||
};
|
};
|
||||||
|
if platform.needs_proton(&orign_shortcut) {
|
||||||
|
shortcuts_to_proton.push(format!("{}", shortcut_owned.app_id));
|
||||||
|
}
|
||||||
current_shortcuts.push(shortcut_owned.clone());
|
current_shortcuts.push(shortcut_owned.clone());
|
||||||
}
|
}
|
||||||
|
if shortcuts_to_proton.len() > 0 {
|
||||||
|
setup_proton_games(shortcuts_to_proton.as_slice());
|
||||||
|
}
|
||||||
|
|
||||||
let name = platform.name();
|
let name = platform.name();
|
||||||
return Some((name.to_string(), current_shortcuts));
|
return Some((name.to_string(), current_shortcuts));
|
||||||
}
|
}
|
||||||
|
|||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
{
|
||||||
|
"1102190"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"0"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "75"
|
||||||
|
}
|
||||||
|
"337340"
|
||||||
|
{
|
||||||
|
"name" "proton_7"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"1794680"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"3601140154"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"3230402366"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"3065048582"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"4068205213"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"3667283406"
|
||||||
|
{
|
||||||
|
"name" ""
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"2719403116"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"43"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+104
@@ -0,0 +1,104 @@
|
|||||||
|
"InstallConfigStore"
|
||||||
|
{
|
||||||
|
"Software"
|
||||||
|
{
|
||||||
|
"Valve"
|
||||||
|
{
|
||||||
|
"Steam"
|
||||||
|
{
|
||||||
|
"AutoUpdateWindowEnabled" "0"
|
||||||
|
"ipv6check_http_state" "bad"
|
||||||
|
"ipv6check_udp_state" "bad"
|
||||||
|
"ShaderCacheManager"
|
||||||
|
{
|
||||||
|
"HasCurrentBucket" "1"
|
||||||
|
"ProcessingQueue" ""
|
||||||
|
"EnableShaderBackgroundProcessing" "1"
|
||||||
|
}
|
||||||
|
"Rate" "30000"
|
||||||
|
"LastConfigstoreUploadTime" "1648654726"
|
||||||
|
"CompatToolMapping"
|
||||||
|
{
|
||||||
|
"1102190"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"0"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "75"
|
||||||
|
}
|
||||||
|
"337340"
|
||||||
|
{
|
||||||
|
"name" "proton_7"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"1794680"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"3601140154"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"3230402366"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"3065048582"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"4068205213"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"3667283406"
|
||||||
|
{
|
||||||
|
"name" ""
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"2719403116"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"43"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"Music"
|
||||||
|
{
|
||||||
|
"LocalLibrary"
|
||||||
|
{
|
||||||
|
"Directories"
|
||||||
|
{
|
||||||
|
"0" "2"
|
||||||
|
"1" "3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+116
@@ -0,0 +1,116 @@
|
|||||||
|
"InstallConfigStore"
|
||||||
|
{
|
||||||
|
"Software"
|
||||||
|
{
|
||||||
|
"Valve"
|
||||||
|
{
|
||||||
|
"Steam"
|
||||||
|
{
|
||||||
|
"AutoUpdateWindowEnabled" "0"
|
||||||
|
"ipv6check_http_state" "bad"
|
||||||
|
"ipv6check_udp_state" "bad"
|
||||||
|
"ShaderCacheManager"
|
||||||
|
{
|
||||||
|
"HasCurrentBucket" "1"
|
||||||
|
"ProcessingQueue" ""
|
||||||
|
"EnableShaderBackgroundProcessing" "1"
|
||||||
|
}
|
||||||
|
"Rate" "30000"
|
||||||
|
"LastConfigstoreUploadTime" "1648654726"
|
||||||
|
"CompatToolMapping"
|
||||||
|
{
|
||||||
|
"1102190"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"0"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "75"
|
||||||
|
}
|
||||||
|
"337340"
|
||||||
|
{
|
||||||
|
"name" "proton_7"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"1794680"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"3601140154"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"3230402366"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"3065048582"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"4068205213"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"3667283406"
|
||||||
|
{
|
||||||
|
"name" ""
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"2719403116"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"43"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"42"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
"44"
|
||||||
|
{
|
||||||
|
"name" "proton_experimental"
|
||||||
|
"config" ""
|
||||||
|
"Priority" "250"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"Music"
|
||||||
|
{
|
||||||
|
"LocalLibrary"
|
||||||
|
{
|
||||||
|
"Directories"
|
||||||
|
{
|
||||||
|
"0" "2"
|
||||||
|
"1" "3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+1
-1
@@ -202,8 +202,8 @@ fn update_ui_with_settings(ui: &mut UserInterface, settings: &Settings) {
|
|||||||
#[cfg(not(target_family = "unix"))]
|
#[cfg(not(target_family = "unix"))]
|
||||||
{
|
{
|
||||||
ui.gog_winedrive_input.hide();
|
ui.gog_winedrive_input.hide();
|
||||||
|
ui.enable_heroic_checkbox.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.enable_uplay_checkbox.set_value(settings.uplay.enabled);
|
ui.enable_uplay_checkbox.set_value(settings.uplay.enabled);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use steam_shortcuts_util::shortcut::{Shortcut, ShortcutOwned};
|
use steam_shortcuts_util::shortcut::{Shortcut, ShortcutOwned};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub(crate) struct Game {
|
pub(crate) struct Game {
|
||||||
pub(crate) name: String,
|
pub(crate) name: String,
|
||||||
pub(crate) icon: String,
|
pub(crate) icon: String,
|
||||||
|
|||||||
@@ -42,6 +42,16 @@ impl Platform<Game, Box<dyn Error>> for Uplay {
|
|||||||
fn create_symlinks(&self) -> bool {
|
fn create_symlinks(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn needs_proton(&self, _input: &Game) -> bool {
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
return false;
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
{
|
||||||
|
//TODO update this when uplay gets proton support on linux
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
|
|||||||
Reference in New Issue
Block a user