Skip to content

Commit

Permalink
#209: Fall back to Lutris 'exe' field when 'working_dir' is missing
Browse files Browse the repository at this point in the history
  • Loading branch information
mtkennerly committed May 21, 2023
1 parent e86bad5 commit b865cce
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 12 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## Unreleased

* Fixed:
* When a Lutris game file does not include the `game > working_dir` field,
Ludusavi will now try to fall back to the `game > exe` field and cut off the file name.
Ludusavi will also log a more specific message when an expected field is missing.

## v0.18.1 (2023-05-21)

* Fixed:
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ along with the root's type:
When using Wine prefixes with Heroic, Ludusavi will back up the `*.reg` files
if the game is known to have registry-based saves.
* For a Lutris root, this should be the folder containing the `games` subdirectory.

Ludusavi expects the game YAML files to contain a few fields,
particularly `name`, `game_slug`, and either `game.working_dir` or `game.exe`.
Games will be skipped if they don't have the necessary fields.
* For the "other" root type and the remaining store-specific roots,
this should be a folder whose direct children are individual games.
For example, in the Epic Games store, this would be what you choose as the
Expand Down
47 changes: 35 additions & 12 deletions src/scan/launchers/lutris.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ use crate::{
struct LutrisGame {
game: GameSection,
/// ID of the game itself.
game_slug: String,
game_slug: Option<String>,
/// Human-readable.
name: String,
name: Option<String>,
}

#[derive(serde::Deserialize)]
struct GameSection {
exe: Option<StrictPath>,
prefix: Option<StrictPath>,
working_dir: StrictPath,
working_dir: Option<StrictPath>,
}

pub fn scan(root: &RootsConfig, title_finder: &TitleFinder) -> HashMap<String, LauncherGame> {
Expand All @@ -39,7 +40,12 @@ pub fn scan(root: &RootsConfig, title_finder: &TitleFinder) -> HashMap<String, L
continue;
};

let official_title = title_finder.find_one(&[game.name.to_owned()], &None, &None, true, true, false);
let (Some(game_slug), Some(name)) = (game.game_slug.clone(), game.name.clone()) else {
log::info!("Skipping Lutris game file without `game_slug` and `name` fields: {}", spec.render());
continue;
};

let official_title = title_finder.find_one(&[name.clone()], &None, &None, true, true, false);
let prefix = game.game.prefix;
let platform = Some(match &prefix {
Some(_) => Os::Windows,
Expand All @@ -50,28 +56,45 @@ pub fn scan(root: &RootsConfig, title_finder: &TitleFinder) -> HashMap<String, L
Some(title) => {
log::trace!(
"Recognized Lutris game: '{title}' from '{}' (slug: '{}')",
&game.name,
&game.game_slug
&name,
&game_slug
);
title
}
None => {
let log_message = format!(
"Unrecognized Lutris game: '{}' (slug: '{}')",
&game.name, &game.game_slug
);
let log_message = format!("Unrecognized Lutris game: '{}' (slug: '{}')", &name, &game_slug);
if std::env::var(ENV_DEBUG).is_ok() {
eprintln!("{log_message}");
}
log::info!("{log_message}");
game.name
name
}
};

let install_dir = if let Some(working_dir) = game.game.working_dir.as_ref() {
working_dir.clone()
} else if let Some(exe) = game.game.exe.as_ref() {
if let Some(parent) = exe.parent() {
parent
} else {
log::info!(
"Skipping Lutris game file with indeterminate parent folder of exe: {}",
spec.render()
);
continue;
}
} else {
log::info!(
"Skipping Lutris game file without `working_dir` and `exe` fields: {}",
spec.render()
);
continue;
};

games.insert(
title,
LauncherGame {
install_dir: game.game.working_dir,
install_dir,
prefix,
platform,
},
Expand Down

0 comments on commit b865cce

Please sign in to comment.