mirror of
https://github.com/djibux/BoilR.git
synced 2026-09-01 05:53:41 +02:00
Initial playnite support (#310)
This commit is contained in:
@@ -14,6 +14,10 @@ mod minigalaxy;
|
||||
#[cfg(not(target_family = "unix"))]
|
||||
mod amazon;
|
||||
|
||||
#[cfg(not(target_family = "unix"))]
|
||||
mod playnite;
|
||||
|
||||
|
||||
|
||||
mod gog;
|
||||
mod itch;
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::collections::HashMap;
|
||||
use super::GamesPlatform;
|
||||
|
||||
use crate::settings::load_setting_sections;
|
||||
const PLATFORM_NAMES: [&str; 12] = [
|
||||
const PLATFORM_NAMES: [&str; 13] = [
|
||||
"amazon",
|
||||
"bottles",
|
||||
"epic_games",
|
||||
@@ -17,6 +17,7 @@ const PLATFORM_NAMES: [&str; 12] = [
|
||||
"origin",
|
||||
"uplay",
|
||||
"minigalaxy",
|
||||
"playnite",
|
||||
];
|
||||
|
||||
pub type Platforms = Vec<Box<dyn GamesPlatform>>;
|
||||
@@ -32,8 +33,10 @@ pub fn load_platform<A: AsRef<str>, B: AsRef<str>>(
|
||||
{
|
||||
//Windows only platforms
|
||||
use super::amazon::AmazonPlatform;
|
||||
use super::playnite::PlaynitePlatform;
|
||||
match name {
|
||||
"amazon" => return load::<AmazonPlatform>(s),
|
||||
"playnite" => return load::<PlaynitePlatform>(s),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -58,7 +61,7 @@ pub fn load_platform<A: AsRef<str>, B: AsRef<str>>(
|
||||
}
|
||||
}
|
||||
|
||||
//Common platforms
|
||||
//Common platforms
|
||||
use super::egs::EpicPlatform;
|
||||
use super::gog::GogPlatform;
|
||||
use super::itch::ItchPlatform;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
mod playnite_platform;
|
||||
mod playnite_parser;
|
||||
pub use playnite_platform::PlaynitePlatform;
|
||||
@@ -0,0 +1,37 @@
|
||||
use nom::{
|
||||
bytes::{
|
||||
complete::{take_until, take_while},
|
||||
streaming::take,
|
||||
},
|
||||
character::is_alphanumeric,
|
||||
multi::many0,
|
||||
IResult,
|
||||
};
|
||||
|
||||
pub(crate) struct NamesAndId {
|
||||
pub(crate) name: String,
|
||||
pub(crate) id: String,
|
||||
}
|
||||
|
||||
pub(crate) fn parse_db<'a>(content: &'a [u8]) -> nom::IResult<&'a [u8], Vec<NamesAndId>> {
|
||||
many0(parse_game)(content)
|
||||
}
|
||||
|
||||
fn parse_game(i: &[u8]) -> nom::IResult<&[u8], NamesAndId> {
|
||||
let (i, _taken) = take_until("_id")(i)?;
|
||||
let (i, _taken) = take_until("Image")(i)?;
|
||||
let (i, prefix_and_id) = take_until("\\")(i)?;
|
||||
let id_bytes = prefix_and_id
|
||||
.split(|b| *b == 0 as u8)
|
||||
.last()
|
||||
.unwrap_or_default();
|
||||
let id = String::from_utf8_lossy(id_bytes).to_string();
|
||||
|
||||
let (i, _taken) = take_until("InstallSizeGroup")(i)?;
|
||||
let (i, _taken) = take_until("Name")(i)?;
|
||||
let (i, _taken) = take(4usize)(i)?;
|
||||
let (i, _taken) = take_while(|b| !is_alphanumeric(b))(i)?;
|
||||
let (i, name_bytes) = take_while(|b| b != 0)(i)?;
|
||||
let name = String::from_utf8_lossy(name_bytes).to_string();
|
||||
IResult::Ok((i, NamesAndId { id, name }))
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
env,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use steam_shortcuts_util::{shortcut::ShortcutOwned, Shortcut};
|
||||
|
||||
use crate::platforms::{load_settings, to_shortcuts_simple, FromSettingsString, GamesPlatform};
|
||||
|
||||
use super::playnite_parser::parse_db;
|
||||
|
||||
impl FromSettingsString for PlaynitePlatform {
|
||||
fn from_settings_string<S: AsRef<str>>(s: S) -> Self {
|
||||
PlaynitePlatform {
|
||||
settings: load_settings(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PlaynitePlatform {
|
||||
pub settings: PlayniteSettings,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct PlayniteSettings {
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
impl Default for PlayniteSettings {
|
||||
fn default() -> Self {
|
||||
Self { enabled: true }
|
||||
}
|
||||
}
|
||||
|
||||
impl GamesPlatform for PlaynitePlatform {
|
||||
fn name(&self) -> &str {
|
||||
"Playnite"
|
||||
}
|
||||
|
||||
fn code_name(&self) -> &str {
|
||||
"playnite"
|
||||
}
|
||||
|
||||
fn enabled(&self) -> bool {
|
||||
self.settings.enabled
|
||||
}
|
||||
|
||||
fn get_shortcut_info(&self) -> eyre::Result<Vec<crate::platforms::ShortcutToImport>> {
|
||||
to_shortcuts_simple(self.get_playnite_games())
|
||||
}
|
||||
|
||||
fn get_settings_serilizable(&self) -> String {
|
||||
toml::to_string(&self.settings).unwrap_or_default()
|
||||
}
|
||||
|
||||
fn render_ui(&mut self, ui: &mut egui::Ui) {
|
||||
ui.heading("Playnite");
|
||||
ui.checkbox(&mut self.settings.enabled, "Import from Playnite");
|
||||
}
|
||||
}
|
||||
|
||||
impl PlaynitePlatform {
|
||||
fn get_playnite_games(&self) -> eyre::Result<Vec<PlayniteGame>> {
|
||||
let mut res = vec![];
|
||||
let app_data_path = env::var("APPDATA")?;
|
||||
let app_data_local_path = env::var("LOCALAPPDATA")?;
|
||||
let launcher_path = Path::new(&app_data_local_path)
|
||||
.join("Playnite")
|
||||
.join("Playnite.DesktopApp.exe");
|
||||
if !launcher_path.exists() {
|
||||
return Err(eyre::eyre!("Did not find Playnite installation"));
|
||||
}
|
||||
let launcher_path = launcher_path.to_string_lossy().to_string();
|
||||
let playnite_folder = Path::new(&app_data_path).join("Playnite");
|
||||
let games_file_path = playnite_folder.join("library").join("games.db");
|
||||
if games_file_path.exists() {
|
||||
let games_bytes = std::fs::read(&games_file_path).unwrap();
|
||||
let (_, games) = parse_db(&games_bytes).map_err(|e| eyre::eyre!(e.to_string()))?;
|
||||
for game in games {
|
||||
res.push(PlayniteGame {
|
||||
id: game.id,
|
||||
launcher_path: launcher_path.clone().into(),
|
||||
name: game.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PlayniteGame> for ShortcutOwned {
|
||||
fn from(game: PlayniteGame) -> Self {
|
||||
let launch = format!("--hidesplashscreen --start {}", game.id);
|
||||
let exe = game.launcher_path.to_string_lossy().to_string();
|
||||
let start_dir = game
|
||||
.launcher_path
|
||||
.parent()
|
||||
.unwrap_or_else(|| Path::new(""))
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
Shortcut::new(
|
||||
"0",
|
||||
game.name.as_str(),
|
||||
exe.as_str(),
|
||||
start_dir.as_str(),
|
||||
"",
|
||||
"",
|
||||
launch.as_str(),
|
||||
)
|
||||
.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PlayniteGame {
|
||||
pub name: String,
|
||||
pub id: String,
|
||||
pub launcher_path: PathBuf,
|
||||
}
|
||||
Reference in New Issue
Block a user