Skip to content

Commit

Permalink
0.3.9 (#130)
Browse files Browse the repository at this point in the history
Show owned games that have no engine detected. Can't really do anything
with them, but eh.
Show GOG games on owned tab (can't deduce engine for now, so also pretty
useless).
Stop showing superfluous scan errors popups, will keep it to the error
logs.
Mark unimplemented features on the filter menu (so people don't think
you're supposed to be able to find owned games from Epic and Xbox yet).
  • Loading branch information
Raicuparta authored Jan 3, 2024
2 parents 7660a44 + 38747b5 commit 0d2e3eb
Show file tree
Hide file tree
Showing 19 changed files with 163 additions and 103 deletions.
2 changes: 1 addition & 1 deletion backend/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion backend/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rai-pal"
version = "0.3.8"
version = "0.4.0"
authors = ["Raicuparta"]
license = "GPL-3.0-or-later"
repository = "https://github.com/Raicuparta/rai-pal"
Expand Down
19 changes: 15 additions & 4 deletions backend/src/game_engines/unity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ use std::{
Path,
PathBuf,
},
time::Instant,
};

use lazy_regex::regex_captures;
use log::error;

use crate::{
debug::LoggableInstant,
game_engines::game_engine::{
GameEngine,
GameEngineBrand,
Expand Down Expand Up @@ -172,10 +174,16 @@ fn get_alt_architecture(game_path: &Path) -> Option<Architecture> {
None
}

pub fn get_engine(game_path: &Path) -> Option<GameExecutable> {
if is_unity_exe(game_path) {
pub fn get_executable(game_path: &Path) -> Option<GameExecutable> {
let now = &mut Instant::now();
let executable = if is_unity_exe(game_path) {
now.log_next("check if is unity exe");
let (operating_system, architecture) =
get_os_and_architecture(game_path).unwrap_or((None, None));
now.log_next("get os and arch");

let version = get_version(game_path);
now.log_next("get unity version");

Some(GameExecutable {
path: game_path.to_path_buf(),
Expand All @@ -185,10 +193,13 @@ pub fn get_engine(game_path: &Path) -> Option<GameExecutable> {
scripting_backend: get_scripting_backend(game_path),
engine: Some(GameEngine {
brand: GameEngineBrand::Unity,
version: get_version(game_path),
version,
}),
})
} else {
None
}
};
now.log_next("get unity executable");

executable
}
20 changes: 16 additions & 4 deletions backend/src/game_engines/unreal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::{
Path,
PathBuf,
},
time::Instant,
};

use lazy_regex::{
Expand All @@ -23,6 +24,7 @@ use pelite::{
};

use crate::{
debug::LoggableInstant,
game_engines::game_engine::{
GameEngine,
GameEngineBrand,
Expand Down Expand Up @@ -220,12 +222,19 @@ fn is_unreal_exe(game_path: &Path) -> bool {
false
}

pub fn get_engine(launch_path: &Path) -> Option<GameExecutable> {
if is_unreal_exe(launch_path) {
pub fn get_executable(launch_path: &Path) -> Option<GameExecutable> {
let now = &mut Instant::now();
let executable = if is_unreal_exe(launch_path) {
now.log_next("check if is unreal exe");
let path = get_actual_unreal_binary(launch_path);
now.log_next("get actual unreal binary");

let (operating_system, architecture) =
get_os_and_architecture(&path).unwrap_or((None, None));
now.log_next("get os and arch");

let version = get_version(launch_path, architecture.unwrap_or(Architecture::X64));
now.log_next("get unreal version");

Some(GameExecutable {
path,
Expand All @@ -234,10 +243,13 @@ pub fn get_engine(launch_path: &Path) -> Option<GameExecutable> {
scripting_backend: None,
engine: Some(GameEngine {
brand: GameEngineBrand::Unreal,
version: get_version(launch_path, architecture.unwrap_or(Architecture::X64)),
version,
}),
})
} else {
None
}
};
now.log_next("get unreal executable");

executable
}
25 changes: 9 additions & 16 deletions backend/src/game_executable.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
use std::{
fs,
fs::{
self,
File,
},
io::Read,
path::{
Path,
PathBuf,
},
time::Instant,
};

use goblin::{
Expand All @@ -13,6 +18,7 @@ use goblin::{
use log::error;

use crate::{
debug::LoggableInstant,
game_engines::{
game_engine::GameEngine,
unity::{
Expand Down Expand Up @@ -88,22 +94,9 @@ pub fn get_os_and_architecture(
}

impl GameExecutable {
pub fn new(path: &Path) -> Self {
pub fn new(path: &Path) -> Option<Self> {
let normalized_path = normalize_path(path);

unity::get_engine(&normalized_path)
.or_else(|| unreal::get_engine(&normalized_path))
.unwrap_or_else(|| {
let (operating_system, architecture) =
get_os_and_architecture(&normalized_path).unwrap_or((None, None));

Self {
engine: None,
architecture,
operating_system,
path: normalized_path,
scripting_backend: None,
}
})
unity::get_executable(&normalized_path).or_else(|| unreal::get_executable(&normalized_path))
}
}
31 changes: 26 additions & 5 deletions backend/src/installed_game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ use std::{
Path,
PathBuf,
},
time::Instant,
};

use crate::{
debug::LoggableInstant,
game_executable::GameExecutable,
game_mod,
game_mode::GameMode,
Expand All @@ -25,6 +27,7 @@ use crate::{
self,
appinfo::SteamLaunchOption,
},
Error,
Result,
};

Expand Down Expand Up @@ -52,13 +55,16 @@ impl InstalledGame {
steam_launch: Option<&SteamLaunchOption>,
thumbnail_url: Option<String>,
) -> Option<Self> {
let now = &mut Instant::now();
// Games exported by Unity always have one of these extensions.
const VALID_EXTENSIONS: [&str; 3] = ["exe", "x86_64", "x86"];

if !path.is_file() {
return None;
}

now.log_next("check if game exists");

// We ignore games that don't have an extension.
let extension = path.extension()?.to_str()?;

Expand All @@ -75,21 +81,36 @@ impl InstalledGame {

let game_mode = steam_launch.map_or(GameMode::Flat, SteamLaunchOption::get_game_mode);

Some(Self {
now.log_next(&format!(
"before creating installed game ({})",
path.display()
));

let installed_game = Some(Self {
id: hash_path(path),
name: name.to_string(),
provider_id,
discriminator,
steam_launch: steam_launch.cloned(),
installed_mod_versions: HashMap::default(),
executable: GameExecutable::new(path),
executable: GameExecutable::new(path)?,
thumbnail_url,
game_mode,
})
});

now.log_next("after creating installed game");

installed_game
}

pub fn refresh_executable(&mut self) {
self.executable = GameExecutable::new(&self.executable.path);
pub fn refresh_executable(&mut self) -> Result {
if let Some(executable) = GameExecutable::new(&self.executable.path) {
self.executable = executable;
} else {
return Err(Error::FailedToGetGameFromPath(self.executable.path.clone()));
}

Ok(())
}

pub fn update_available_mods(&mut self, data_map: &game_mod::CommonDataMap) {
Expand Down
4 changes: 1 addition & 3 deletions backend/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,9 +371,7 @@ async fn update_data(handle: AppHandle) -> Result {
match installed_games {
Ok(games) => games,
Err(err) => {
handle.emit_error(format!(
"Error getting installed games for provider ({provider_id}): {err}"
));
error!("Error getting installed games for provider ({provider_id}): {err}");
Vec::default()
}
}
Expand Down
4 changes: 2 additions & 2 deletions backend/src/owned_game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ serializable_struct!(OwnedGame {
pub name: String,
pub installed: bool,
pub os_list: HashSet<OperatingSystem>,
pub engine: GameEngineBrand,
pub engine: Option<GameEngineBrand>,
pub release_date: i32,
pub thumbnail_url: String,
pub game_mode: GameMode,
pub game_mode: Option<GameMode>,
pub uevr_score: Option<UevrScore>,
});

Expand Down
40 changes: 19 additions & 21 deletions backend/src/providers/gog_provider.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::HashSet;

use async_trait::async_trait;

use super::provider::ProviderId;
Expand Down Expand Up @@ -44,26 +46,22 @@ impl ProviderActions for GogProvider {
}

async fn get_owned_games(&self) -> Result<Vec<OwnedGame>> {
Ok(Vec::default())

// TODO figure out if this is worth implementing.
// Ok(game_scanner::gog::games()
// .unwrap_or_default()
// .iter()
// .map(|game| OwnedGame {
// // TODO should add a constructor to OwnedGame to avoid ID collisions and stuff.
// id: game.id.clone(),
// provider_id: *Self::ID,
// name: game.name.clone(),
// installed: false, // TODO
// os_list: HashSet::default(),
// // Make engine optional?
// engine: GameEngineBrand::Unity,
// release_date: 0,
// thumbnail_url: String::default(),
// game_mode: GameMode::Flat,
// uevr_score: None,
// })
// .collect())
Ok(game_scanner::gog::games()
.unwrap_or_default()
.iter()
.map(|game| OwnedGame {
// TODO should add a constructor to OwnedGame to avoid ID collisions and stuff.
id: game.id.clone(),
provider_id: *Self::ID,
name: game.name.clone(),
installed: false, // TODO
os_list: HashSet::default(),
engine: None,
release_date: 0, // TODO
thumbnail_url: String::default(), // TODO Maybe possible to get from the sqlite db?
game_mode: None,
uevr_score: None,
})
.collect())
}
}
28 changes: 14 additions & 14 deletions backend/src/providers/steam_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,12 @@ impl ProviderActions for SteamProvider {
}

async fn get_owned_games(&self) -> Result<Vec<OwnedGame>> {
Ok(id_lists::get()
.await?
let steam_games = id_lists::get().await?;
Ok(self
.app_info_file
.apps
.iter()
.filter_map(|steam_id_data| {
let id_number = steam_id_data.id.parse::<u32>().ok()?;

let app_info = self.app_info_file.apps.get(&id_number)?;

.filter_map(|(steam_id, app_info)| {
let os_list: HashSet<_> = app_info
.launch_options
.iter()
Expand Down Expand Up @@ -154,7 +152,7 @@ impl ProviderActions for SteamProvider {
// Would be smarter to actually parse assets.vdf and extract all the ids,
// but I didn't feel like figuring out how to parse another binary vdf.
// Maybe later. But most likely never.
BytesRegex::new(&steam_id_data.id)
BytesRegex::new(&steam_id.to_string())
.map_or(false, |regex| regex.is_match(&assets_cache_bytes))
});

Expand All @@ -164,7 +162,7 @@ impl ProviderActions for SteamProvider {

let installed = self
.steam_dir
.app(id_number)
.app(*steam_id)
.map_or(false, |steam_app| steam_app.is_some());

let release_date = app_info
Expand All @@ -182,17 +180,19 @@ impl ProviderActions for SteamProvider {
GameMode::Flat
};

let steam_game = steam_games.get(&steam_id.to_string());

Some(OwnedGame {
id: steam_id_data.id.clone(),
id: steam_id.to_string(),
provider_id: *Self::ID,
name: app_info.name.clone(),
installed,
os_list,
engine: steam_id_data.engine,
engine: steam_game.map(|game| game.engine),
release_date,
thumbnail_url: get_steam_thumbnail(&steam_id_data.id),
game_mode,
uevr_score: steam_id_data.uevr_score,
thumbnail_url: get_steam_thumbnail(&steam_id.to_string()),
game_mode: Some(game_mode),
uevr_score: steam_game.and_then(|game| game.uevr_score),
})
})
.collect())
Expand Down
Loading

0 comments on commit 0d2e3eb

Please sign in to comment.