From 4d71aca0a61e9eb4fbfc9cebd35f9b6c0d34a1a0 Mon Sep 17 00:00:00 2001 From: Philip Kristoffersen Date: Tue, 8 Mar 2022 15:38:27 +0100 Subject: [PATCH 1/3] Initial lutris folder with test output --- src/lutris/test_output.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/lutris/test_output.txt diff --git a/src/lutris/test_output.txt b/src/lutris/test_output.txt new file mode 100644 index 0000000..422cad4 --- /dev/null +++ b/src/lutris/test_output.txt @@ -0,0 +1,19 @@ + 7 | 7 Billion Humans | 7-billion-humans | steam | - + 1 | Cave Story+ | cave-story | steam | - + 15 | Dead Cells | dead-cells | steam | - + 6 | Dicey Dungeons | dicey-dungeons | steam | - + 12 | Finding Paradise | finding-paradise | steam | - + 17 | Griftlands | griftlands | steam | - + 4 | Gunpoint | gunpoint | steam | - + 5 | Impostor Factory | impostor-factory | steam | - + 3 | Kentucky Route Zero | kentucky-route-zero | steam | - + 13 | Monster Train | monster-train | steam | - + 19 | My Test Game | my-test-game | linux | - + 8 | Owlboy | owlboy | steam | - + 16 | Papers, Please | papers-please | steam | - + 11 | Reventure | reventure | steam | - + 2 | Slay the Spire | slay-the-spire | steam | - + 9 | Space Pirates and Zombies | space-pirates-and-zombies | steam | - + 10 | The Detail | the-detail | steam | - + 14 | The Henry Stickmin Collection | the-henry-stickmin-collection | steam | - + 18 | Vampire Survivors | vampire-survivors | steam | - From 36dca25297dd0278b5d178e71188564209928ed6 Mon Sep 17 00:00:00 2001 From: Philip Kristoffersen Date: Tue, 8 Mar 2022 21:15:20 +0100 Subject: [PATCH 2/3] Add support for lutris --- src/defaultconfig.toml | 3 ++ src/lutris/game_list_parser.rs | 78 ++++++++++++++++++++++++++++++++++ src/lutris/lutris_game.rs | 25 +++++++++++ src/lutris/lutris_platform.rs | 51 ++++++++++++++++++++++ src/lutris/mod.rs | 4 ++ src/lutris/settings.rs | 7 +++ src/main.rs | 1 + src/settings.rs | 13 ++++-- src/sync/synchronization.rs | 8 ++++ 9 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 src/lutris/game_list_parser.rs create mode 100644 src/lutris/lutris_game.rs create mode 100644 src/lutris/lutris_platform.rs create mode 100644 src/lutris/mod.rs create mode 100644 src/lutris/settings.rs diff --git a/src/defaultconfig.toml b/src/defaultconfig.toml index 9d512e0..74d4c5e 100644 --- a/src/defaultconfig.toml +++ b/src/defaultconfig.toml @@ -26,3 +26,6 @@ create_symlinks = true [steamgrid_db] enabled = true prefer_animated = false + +[lutris] +enabled = true diff --git a/src/lutris/game_list_parser.rs b/src/lutris/game_list_parser.rs new file mode 100644 index 0000000..d063abb --- /dev/null +++ b/src/lutris/game_list_parser.rs @@ -0,0 +1,78 @@ +use super::lutris_game::LutrisGame; + +pub fn parse_lutris_games<'a>(input: &'a str) -> Vec { + input + .split("\n") + .into_iter() + .filter(|s| !s.is_empty()) + .filter_map(parse_line) + .collect() +} + +fn parse_line<'a>(input: &'a str) -> Option { + let mut sections = input.split("|"); + if sections.clone().count() < 4 { + return None; + } + let index = sections.next().unwrap().trim(); + let name = sections.next().unwrap().trim(); + let id = sections.next().unwrap().trim(); + let platform = sections.next().unwrap().trim(); + + Some(LutrisGame { + id:id.to_string(), + index:index.to_string(), + name:name.to_string(), + platform:platform.to_string(), + }) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn can_parse_output() { + let content = include_str!("test_output.txt"); + + let games = parse_lutris_games(content); + + assert_eq!(19, games.len()); + } + + #[test] + fn reads_index() { + let content = include_str!("test_output.txt"); + + let games = parse_lutris_games(content); + + assert_eq!(games[0].index, "7"); + } + + #[test] + fn reads_name() { + let content = include_str!("test_output.txt"); + + let games = parse_lutris_games(content); + + assert_eq!(games[1].name, "Cave Story+"); + } + + #[test] + fn reads_id() { + let content = include_str!("test_output.txt"); + + let games = parse_lutris_games(content); + + assert_eq!(games[3].id, "dicey-dungeons"); + } + + #[test] + fn reads_platform() { + let content = include_str!("test_output.txt"); + + let games = parse_lutris_games(content); + + assert_eq!(games[18].platform, "steam"); + } +} diff --git a/src/lutris/lutris_game.rs b/src/lutris/lutris_game.rs new file mode 100644 index 0000000..89ab7ee --- /dev/null +++ b/src/lutris/lutris_game.rs @@ -0,0 +1,25 @@ +use steam_shortcuts_util::{shortcut::ShortcutOwned, Shortcut}; + +#[derive(Clone)] +pub struct LutrisGame { + pub index: String, + pub name: String, + pub id: String, + pub platform: String, +} + +impl From for ShortcutOwned { + fn from(game: LutrisGame) -> Self { + let options = format!("lutris:rungame/{}", game.id); + Shortcut::new( + 0, + game.name.as_str(), + "lutris", + "", + "", + "", + &options.as_str(), + ) + .to_owned() + } +} diff --git a/src/lutris/lutris_platform.rs b/src/lutris/lutris_platform.rs new file mode 100644 index 0000000..4d94db2 --- /dev/null +++ b/src/lutris/lutris_platform.rs @@ -0,0 +1,51 @@ +use super::game_list_parser::parse_lutris_games; +use super::lutris_game::LutrisGame; +use super::settings::LutrisSettings; +use crate::platform::{Platform, SettingsValidity}; +use std::error::Error; +use std::process::Command; + +pub struct LutrisPlatform { + pub settings: LutrisSettings, +} + + +impl Platform> for LutrisPlatform { + fn enabled(&self) -> bool { + self.settings.enabled + } + + fn name(&self) -> &str { + "Lutris" + } + + fn get_shortcuts(&self) -> Result, Box> { + let default_lutris_exe = "lutris".to_string(); + let lutris_executable = self.settings.executable.as_ref().unwrap_or(&default_lutris_exe); + let lutris_command = Command::new(lutris_executable).arg("-lo").output()?; + let output = String::from_utf8_lossy(&lutris_command.stdout).to_string(); + let games = parse_lutris_games(output.as_str()); + let mut res = vec![]; + for game in games { + if game.platform != "steam" { + res.push(game); + } + } + Ok(res) + } + + #[cfg(target_family = "unix")] + fn create_symlinks(&self) -> bool { + false + } + + fn settings_valid(&self) -> crate::platform::SettingsValidity { + let shortcuts_res = self.get_shortcuts(); + match shortcuts_res { + Ok(_) => SettingsValidity::Valid, + Err(err) => SettingsValidity::Invalid { + reason: format!("{}", err), + }, + } + } +} diff --git a/src/lutris/mod.rs b/src/lutris/mod.rs new file mode 100644 index 0000000..eacdc4f --- /dev/null +++ b/src/lutris/mod.rs @@ -0,0 +1,4 @@ +pub mod game_list_parser; +pub mod lutris_game; +pub mod lutris_platform; +pub mod settings; diff --git a/src/lutris/settings.rs b/src/lutris/settings.rs new file mode 100644 index 0000000..810a6f6 --- /dev/null +++ b/src/lutris/settings.rs @@ -0,0 +1,7 @@ +use serde::{Serialize,Deserialize}; + +#[derive(Debug, Deserialize, Serialize,Clone)] +pub struct LutrisSettings { + pub enabled: bool, + pub executable: Option, +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 6446ece..01aa197 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ mod egs; mod gog; mod itch; +mod lutris; mod legendary; mod origin; mod platform; diff --git a/src/settings.rs b/src/settings.rs index 28a0162..f84863d 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -1,7 +1,13 @@ use crate::{ - egs::EpicGamesLauncherSettings, gog::GogSettings, itch::ItchSettings, - legendary::LegendarySettings, origin::OriginSettings, steam::SteamSettings, - steamgriddb::SteamGridDbSettings, uplay::UplaySettings, + egs::EpicGamesLauncherSettings, + gog::GogSettings, + itch::ItchSettings, + legendary::LegendarySettings, + origin::OriginSettings, + steam::SteamSettings, + steamgriddb::SteamGridDbSettings, + uplay::UplaySettings, + lutris::settings::LutrisSettings, }; use config::{Config, ConfigError, Environment, File}; @@ -19,6 +25,7 @@ pub struct Settings { pub origin: OriginSettings, pub gog: GogSettings, pub uplay: UplaySettings, + pub lutris: LutrisSettings, } impl Settings { diff --git a/src/sync/synchronization.rs b/src/sync/synchronization.rs index 6345fb6..6da64b3 100644 --- a/src/sync/synchronization.rs +++ b/src/sync/synchronization.rs @@ -3,6 +3,7 @@ use steam_shortcuts_util::{shortcut::ShortcutOwned, shortcuts_to_bytes}; use crate::{ egs::EpicPlatform, legendary::LegendaryPlatform, + lutris::lutris_platform::LutrisPlatform, platform::Platform, settings::Settings, steam::{get_shortcuts_for_user, get_shortcuts_paths, ShortcutInfo, SteamUsersInfo}, @@ -111,6 +112,13 @@ fn update_platforms(settings: &Settings, new_user_shortcuts: &mut Vec Date: Tue, 8 Mar 2022 21:20:28 +0100 Subject: [PATCH 3/3] Update readme --- Readme.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Readme.md b/Readme.md index c0080dd..274f01b 100644 --- a/Readme.md +++ b/Readme.md @@ -14,13 +14,13 @@ The goal is that you do not have to leave your Steam library to launch games fro - [x] [Origin](https://www.origin.com) integration (currently only windows, linux comming soon) - [x] [GOG](https://www.gog.com/galaxy) integration - [x] [UPlay](https://ubisoftconnect.com) integration (Windows only) +- [x] [Lutris](https://github.com/lutris/lutris) integration - [x] Cross Platform (Linux & Windows) - [x] UI For configuration - [x] Small (~1.5mb on disk) - [x] Lightweight (~2mb ram) - [x] Fast synchronization (~30ms) - [x] Fast art download (as fast as your internet will take you) -- [ ] [Lutris](https://github.com/lutris/lutris) integration - [ ] XBox/Microsoft Store integration - [ ] Scheduling of synchronization - [ ] Steam Deck support (should work, but need to test when I get one) @@ -70,6 +70,10 @@ create_symlinks = true #Only for Linux, To get around a bug in steam where paths enabled=false #On windows this is default false, on linux default true executable="legendary" #If this value is not defined, "legendary" will be used, it is assumed to be on the path. +[lutris] +enabled=true #Default true +executable="lutris" #The executable to run for lutris, default is "lutris". + [itch] enabled=false #Default false location="C:\\Users\\user\\AppData\\Roaming\\itch" #If this value is not defined, "%APPDATA%itch" will be used on windows, and HOME/.config/itch on linux. @@ -96,7 +100,7 @@ prefer_animated = false #If true, animated images will be prefered over static i ## Tips for Linux -If you are on linux, and want to use one of the launchers that is not available natively, here are a few ways that you can make them work. +If you are on linux, and want to use one of the launchers that is not available natively, i suggest you use Lutris and make sure the BoilR integration for Lutris is enabled (see config section). If you don't want to use launch into Lutris here here are a few ways that you can make them work. ### GOG @@ -118,7 +122,7 @@ I recommend you just use [Legendary](https://github.com/derrod/legendary). But i ### Origin -Currently BoilR can't setup shortcuts to Origin because Origin uses a special link to open games. But I know of a workaround, it is just going to take a bit to make (basicly let Boiler take that url as input and let it call origin with proton settings and the url). +Currently BoilR can't setup shortcuts to Origin, on linux, because Origin uses a special link to open games. But I know of a workaround, it is just going to take a bit to make (basicly let Boiler take that url as input and let it call origin with proton settings and the url). This section will be updated when it is ready. Untill then you can still play origin games thourgh Lutris [here](https://lutris.net/games/origin/)