mirror of
https://github.com/djibux/BoilR.git
synced 2026-09-01 05:53:41 +02:00
Update cargo toml and refactor uplay (#347)
* Update dependencies * Conditional imports for linux * Fix windows warnings * Sample testconfiguration for uplay * Refactor uplay code to remove unsafe blocks * Update version to 1.8.0 * Update cargo-lock for flatpak * Update flatpak appdata with realse 1.8.0 * Update src/platforms/uplay/platform.rs Co-authored-by: Ofacy <github@ofacy.com> --------- Co-authored-by: Ofacy <github@ofacy.com>
This commit is contained in:
co-authored by
Ofacy
parent
c092ffba88
commit
d5f038a2fa
Generated
+588
-429
File diff suppressed because it is too large
Load Diff
+5
-5
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
name = "boilr"
|
name = "boilr"
|
||||||
version = "1.7.22"
|
version = "1.8.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = "^0.21.0"
|
base64 = "^0.21.0"
|
||||||
@@ -15,7 +15,7 @@ serde_json = "^1.0.91"
|
|||||||
|
|
||||||
steam_shortcuts_util = "^1.1.8"
|
steam_shortcuts_util = "^1.1.8"
|
||||||
steamgriddb_api = "^0.3.1"
|
steamgriddb_api = "^0.3.1"
|
||||||
sysinfo = "^0.27.1"
|
sysinfo = "^0.29.0"
|
||||||
eyre = "^0.6.8"
|
eyre = "^0.6.8"
|
||||||
color-eyre = "^0.6.2"
|
color-eyre = "^0.6.2"
|
||||||
dyn-clone = "^1.0.10"
|
dyn-clone = "^1.0.10"
|
||||||
@@ -29,10 +29,10 @@ features = ["serde"]
|
|||||||
version = "^5.4.0"
|
version = "^5.4.0"
|
||||||
|
|
||||||
[dependencies.eframe]
|
[dependencies.eframe]
|
||||||
version = "^0.20.1"
|
version = "^0.22.0"
|
||||||
|
|
||||||
[dependencies.egui]
|
[dependencies.egui]
|
||||||
version = "^0.20.1"
|
version = "^0.22.0"
|
||||||
|
|
||||||
[dependencies.futures]
|
[dependencies.futures]
|
||||||
version = "^0.3.25"
|
version = "^0.3.25"
|
||||||
@@ -62,7 +62,7 @@ version = "^0.7.1"
|
|||||||
winres = "^0.1.12"
|
winres = "^0.1.12"
|
||||||
|
|
||||||
[target."cfg(windows)".dependencies]
|
[target."cfg(windows)".dependencies]
|
||||||
winreg = "^0.10.1"
|
winreg = "^0.50.0"
|
||||||
sqlite = "^0.30.3"
|
sqlite = "^0.30.3"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|||||||
+1734
-1279
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,15 @@ https://hughsie.github.io/oars/index.html
|
|||||||
-->
|
-->
|
||||||
<content_rating type="oars-1.1" />
|
<content_rating type="oars-1.1" />
|
||||||
<releases>
|
<releases>
|
||||||
|
|
||||||
|
<release version="1.8.0" date="2023-05-29">
|
||||||
|
<description>
|
||||||
|
<ul>
|
||||||
|
<li>Update dependencies</li>
|
||||||
|
<li>Support for UPlay</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
<release version="1.7.22" date="2023-05-15">
|
<release version="1.7.22" date="2023-05-15">
|
||||||
<description>
|
<description>
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ pub(crate) struct UplayGame {
|
|||||||
pub(crate) id: String,
|
pub(crate) id: String,
|
||||||
pub(crate) launcher: PathBuf,
|
pub(crate) launcher: PathBuf,
|
||||||
pub(crate) launcher_compat_folder: Option<PathBuf>,
|
pub(crate) launcher_compat_folder: Option<PathBuf>,
|
||||||
pub(crate) launch_id: u8,
|
pub(crate) launch_id: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<UplayGame> for ShortcutOwned {
|
impl From<UplayGame> for ShortcutOwned {
|
||||||
|
|||||||
+103
-74
@@ -3,16 +3,12 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use std::io::Read;
|
|
||||||
use std::io::BufReader;
|
|
||||||
use std::fs::File;
|
|
||||||
|
|
||||||
use crate::platforms::load_settings;
|
use crate::platforms::load_settings;
|
||||||
use crate::platforms::to_shortcuts_simple;
|
use crate::platforms::to_shortcuts_simple;
|
||||||
use crate::platforms::FromSettingsString;
|
use crate::platforms::FromSettingsString;
|
||||||
use crate::platforms::GamesPlatform;
|
use crate::platforms::GamesPlatform;
|
||||||
use crate::platforms::ShortcutToImport;
|
|
||||||
use crate::platforms::NeedsPorton;
|
use crate::platforms::NeedsPorton;
|
||||||
|
use crate::platforms::ShortcutToImport;
|
||||||
|
|
||||||
use super::{game::UplayGame, settings::UplaySettings};
|
use super::{game::UplayGame, settings::UplaySettings};
|
||||||
|
|
||||||
@@ -37,7 +33,6 @@ impl NeedsPorton<UplayPlatform> for UplayGame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn get_uplay_games() -> eyre::Result<Vec<UplayGame>> {
|
fn get_uplay_games() -> eyre::Result<Vec<UplayGame>> {
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
{
|
{
|
||||||
@@ -54,12 +49,13 @@ struct UplayPathData {
|
|||||||
//~/.steam/steam/steamapps/compatdata/X/pfx/drive_c/Program Files (x86)/Ubisoft/Ubisoft Game Launcher/upc.exe
|
//~/.steam/steam/steamapps/compatdata/X/pfx/drive_c/Program Files (x86)/Ubisoft/Ubisoft Game Launcher/upc.exe
|
||||||
exe_path: PathBuf,
|
exe_path: PathBuf,
|
||||||
//~/.steam/steam/steamapps/compatdata/X/pfx/drive_c/Program Files (x86)/Ubisoft/Ubisoft Game Launcher/games/
|
//~/.steam/steam/steamapps/compatdata/X/pfx/drive_c/Program Files (x86)/Ubisoft/Ubisoft Game Launcher/games/
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
games_path: PathBuf,
|
games_path: PathBuf,
|
||||||
//~/.steam/steam/steamapps/compatdata/X
|
//~/.steam/steam/steamapps/compatdata/X
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
compat_folder: Option<PathBuf>,
|
compat_folder: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
fn get_launcher_path() -> eyre::Result<UplayPathData> {
|
fn get_launcher_path() -> eyre::Result<UplayPathData> {
|
||||||
let mut res = UplayPathData::default();
|
let mut res = UplayPathData::default();
|
||||||
@@ -99,11 +95,9 @@ fn get_launcher_path() -> eyre::Result<UplayPathData> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(eyre::eyre!(
|
Err(eyre::eyre!("Could not find uplay launcher"))
|
||||||
"Could not find uplay launcher"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
fn get_launcher_path() -> eyre::Result<UplayPathData> {
|
fn get_launcher_path() -> eyre::Result<UplayPathData> {
|
||||||
let mut res = UplayPathData::default();
|
let mut res = UplayPathData::default();
|
||||||
@@ -162,7 +156,7 @@ fn get_games_from_winreg() -> eyre::Result<Vec<UplayGame>> {
|
|||||||
id,
|
id,
|
||||||
launcher: launcher_path.clone(),
|
launcher: launcher_path.clone(),
|
||||||
launcher_compat_folder: None,
|
launcher_compat_folder: None,
|
||||||
launch_id: 0
|
launch_id: 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,95 +167,107 @@ fn get_games_from_winreg() -> eyre::Result<Vec<UplayGame>> {
|
|||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
fn get_games_from_proton() -> eyre::Result<Vec<UplayGame>> {
|
fn get_games_from_proton() -> eyre::Result<Vec<UplayGame>> {
|
||||||
let mut games = vec![];
|
|
||||||
|
|
||||||
let launcher_path = get_launcher_path()?;
|
let launcher_path = get_launcher_path()?;
|
||||||
let parent = launcher_path.exe_path.parent().unwrap_or_else(|| Path::new("/"));
|
let parent = launcher_path
|
||||||
let file = File::open(parent
|
.exe_path
|
||||||
|
.parent()
|
||||||
|
.unwrap_or_else(|| Path::new("/"));
|
||||||
|
let file = parent
|
||||||
.join("cache")
|
.join("cache")
|
||||||
.join("configuration")
|
.join("configuration")
|
||||||
.join("configurations"))?;
|
.join("configurations");
|
||||||
let mut reader = BufReader::new(file);
|
let buffer = std::fs::read(file)?;
|
||||||
let mut buffer = Vec::new();
|
let splits = get_file_splits(&buffer);
|
||||||
|
let configurations = splits.iter().filter(|s| is_valid_game_config(s));
|
||||||
// Read file into vector.
|
let parsed_configurations= configurations.flat_map(|config| parse_game_config(config));
|
||||||
reader.read_to_end(&mut buffer)?;
|
let games = parsed_configurations.map(|game|{
|
||||||
|
UplayGame{
|
||||||
let mut splits: Vec<String> = Vec::new();
|
name:game.shortcut_name.to_string(),
|
||||||
|
icon: parent.join("data").join("games").join(game.icon_image).to_string_lossy().to_string(),
|
||||||
while !buffer.is_empty() {
|
id : game.register
|
||||||
let game_header = b"version: 2.0";
|
.strip_prefix("HKEY_LOCAL_MACHINE\\SOFTWARE\\Ubisoft\\Launcher\\Installs\\")
|
||||||
let foundindex: usize = match buffer.windows(game_header.len()).position(|window| window == game_header) {
|
.unwrap_or_default()
|
||||||
Some(index) => {index},
|
.strip_suffix("\\InstallDir")
|
||||||
None => {break;},
|
.unwrap_or_default()
|
||||||
};
|
.to_string(),
|
||||||
let (mut first, second) = buffer.split_at(foundindex);
|
launcher : launcher_path.exe_path.clone(),
|
||||||
if first.len() >= 14usize {
|
launcher_compat_folder: launcher_path.compat_folder.clone(),
|
||||||
first = first.split_at(first.len()-14).0;
|
launch_id: game.launch_id
|
||||||
}
|
|
||||||
splits.push(unsafe {std::str::from_utf8_unchecked(first).to_string()});
|
|
||||||
buffer = second.split_at("version: 2.0".len()).1.to_vec();
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
Ok(games.collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GameConfig<'a> {
|
||||||
|
icon_image: &'a str,
|
||||||
|
shortcut_name: &'a str,
|
||||||
|
register: &'a str,
|
||||||
|
launch_id: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_game_config(split: &str) -> Vec<GameConfig> {
|
||||||
|
let mut res = vec![];
|
||||||
for gameconfig in splits {
|
let mut icon_image = "";
|
||||||
if !gameconfig.contains("executables:") {continue};
|
let mut shortcut_name = "";
|
||||||
if !gameconfig.contains("online:") {continue};
|
let mut register = "";
|
||||||
if !gameconfig.contains("shortcut_name:") {continue};
|
|
||||||
if !gameconfig.contains("register:") {continue};
|
|
||||||
|
|
||||||
let mut inonline = false;
|
let mut inonline = false;
|
||||||
let mut shortcut_name: String = "".to_string();
|
|
||||||
let mut game_id: String = "".to_string();
|
|
||||||
let mut icon_image: PathBuf = "".into();
|
|
||||||
let mut launch_id = 0;
|
let mut launch_id = 0;
|
||||||
for line in gameconfig.split('\n') {
|
for line in split.lines().map(|line| line.trim()) {
|
||||||
let trimed = line.trim();
|
if line.starts_with("online:") {
|
||||||
if trimed.starts_with("online:") {
|
|
||||||
inonline = true;
|
inonline = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if trimed.starts_with("offline:") {
|
if line.starts_with("offline:") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if trimed.starts_with("icon_image: ") {
|
if let Some(split) = line.strip_prefix("icon_image: ") {
|
||||||
let split = trimed.split_at("icon_image: ".len()).1;
|
if split.is_empty() {
|
||||||
if split.is_empty() {break}; // invalid config.
|
break;
|
||||||
icon_image = parent.join("data").join("games").join(split);
|
}; // invalid config.
|
||||||
|
icon_image = split;
|
||||||
}
|
}
|
||||||
if !inonline {continue};
|
if !inonline {
|
||||||
if trimed.starts_with("- shortcut_name:") {
|
continue;
|
||||||
let split = trimed.split_at("- shortcut_name:".len()).1;
|
};
|
||||||
if split.is_empty() {break}; // invalid config.
|
if let Some(split) = line.strip_prefix("- shortcut_name: ") {
|
||||||
shortcut_name = split.to_string();
|
if split.is_empty() {
|
||||||
|
break;
|
||||||
|
}; // invalid config.
|
||||||
|
shortcut_name = split;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if trimed.starts_with("register: ") {
|
if let Some(split) = line.strip_prefix("register: ") {
|
||||||
let split = trimed.split_at("register: ".len()).1;
|
if split.is_empty() {
|
||||||
if split.is_empty() {break}; // invalid config.
|
break;
|
||||||
game_id = split
|
}; // invalid config.
|
||||||
.strip_prefix("HKEY_LOCAL_MACHINE\\SOFTWARE\\Ubisoft\\Launcher\\Installs\\").unwrap_or_default()
|
register = split;
|
||||||
.strip_suffix("\\InstallDir").unwrap_or_default().to_string();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if trimed == "denuvo: yes" {
|
if line == "denuvo: yes" {
|
||||||
games.push(UplayGame {
|
res.push(GameConfig {
|
||||||
name: shortcut_name.clone(),
|
icon_image,
|
||||||
icon: icon_image.to_string_lossy().to_string(),
|
shortcut_name,
|
||||||
id: game_id.clone(),
|
register,
|
||||||
launcher: launcher_path.exe_path.clone(),
|
|
||||||
launcher_compat_folder: launcher_path.compat_folder.clone(),
|
|
||||||
launch_id,
|
launch_id,
|
||||||
});
|
});
|
||||||
launch_id += 1;
|
launch_id += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
res
|
||||||
Ok(games)
|
}
|
||||||
|
|
||||||
|
fn is_valid_game_config(config: &str) -> bool {
|
||||||
|
let requires = ["executables:", "online:", "shortcut_name:", "register:"];
|
||||||
|
requires.iter().all(|req| config.contains(req))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_file_splits(buffer: &[u8]) -> Vec<String> {
|
||||||
|
let new_string = String::from_utf8_lossy(buffer);
|
||||||
|
let sections = new_string.split("version: 2.0").map(|s| s.replace('�', ""));
|
||||||
|
sections.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromSettingsString for UplayPlatform {
|
impl FromSettingsString for UplayPlatform {
|
||||||
@@ -298,3 +304,26 @@ impl GamesPlatform for UplayPlatform {
|
|||||||
"uplay"
|
"uplay"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_parse_configuration_file() {
|
||||||
|
let content = include_bytes!("testconfiguration");
|
||||||
|
let splits = get_file_splits(content);
|
||||||
|
assert_eq!(501, splits.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_parse_into_game_config() {
|
||||||
|
let content = include_bytes!("testconfiguration");
|
||||||
|
let splits = get_file_splits(content);
|
||||||
|
let games:Vec<_> = splits.iter().flat_map(|split| parse_game_config(split)).collect();
|
||||||
|
assert_eq!(2, games.len());
|
||||||
|
assert_eq!(Some("For Honor"),games.get(0).map(|h|h.shortcut_name));
|
||||||
|
assert_eq!(Some("WATCH_DOGS® 2"),games.get(1).map(|h|h.shortcut_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+5
-11
@@ -151,8 +151,9 @@ fn try_get_rename_map() -> Result<HashMap<u32, String>, Box<dyn Error>> {
|
|||||||
Ok(deserialized)
|
Ok(deserialized)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone)]
|
#[derive(PartialEq, Clone, Default)]
|
||||||
enum Menues {
|
enum Menues {
|
||||||
|
#[default]
|
||||||
Import,
|
Import,
|
||||||
Settings,
|
Settings,
|
||||||
Images,
|
Images,
|
||||||
@@ -160,12 +161,6 @@ enum Menues {
|
|||||||
Disconnect,
|
Disconnect,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Menues {
|
|
||||||
fn default() -> Menues {
|
|
||||||
Menues::Import
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_games_to_sync(rt: &mut Runtime, platforms: &[Box<dyn GamesPlatform>]) -> GamesToSync {
|
fn create_games_to_sync(rt: &mut Runtime, platforms: &[Box<dyn GamesPlatform>]) -> GamesToSync {
|
||||||
let mut to_sync = vec![];
|
let mut to_sync = vec![];
|
||||||
for platform in platforms {
|
for platform in platforms {
|
||||||
@@ -367,15 +362,14 @@ pub fn run_ui(args: Vec<String>) -> eyre::Result<()>{
|
|||||||
vsync: !no_v_sync,
|
vsync: !no_v_sync,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
eframe::run_native(
|
let run_result = eframe::run_native(
|
||||||
"BoilR",
|
"BoilR",
|
||||||
native_options,
|
native_options,
|
||||||
Box::new(|cc| {
|
Box::new(|cc| {
|
||||||
setup(&cc.egui_ctx);
|
setup(&cc.egui_ctx);
|
||||||
Box::new(app)
|
Box::new(app)
|
||||||
}),
|
}));
|
||||||
);
|
run_result.map_err(|e| eyre::eyre!("Could not initialize: {:?}", e))
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_fullscreen(args: &[String]) -> bool {
|
fn is_fullscreen(args: &[String]) -> bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user