Skip to content

Implement extern get-data command for tmm/r2mm #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,18 @@ pub enum ListSubcommand {
},
}

#[derive(Subcommand, Debug)]
pub enum ExternSubcommand {
/// Get the path of a game with the specified label.
GameData {
/// The identifier of the game to resolve.
///
/// Use the `list` command to query the list of imported and supported games.
#[clap(long)]
game_id: String,
}
}

#[derive(Subcommand, Debug)]
pub enum Commands {
/// Initialize a new project configuration.
Expand Down Expand Up @@ -263,4 +275,10 @@ pub enum Commands {
#[clap(long, default_value = "./")]
project_path: PathBuf,
},

/// Commands for use by external tooling.
Extern {
#[clap(subcommand)]
command: ExternSubcommand,
},
}
24 changes: 10 additions & 14 deletions src/game/ecosystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,19 @@ use crate::TCLI_HOME;
pub async fn get_schema() -> Result<EcosystemSchema, Error> {
let local_schema = TCLI_HOME.join("ecosystem_schema.json");

match local_schema.is_file() {
true => {
let schema_file = File::open(&local_schema)?;
let reader = BufReader::new(&schema_file);
if local_schema.is_file() {
let schema_file = File::open(&local_schema)?;
let reader = BufReader::new(&schema_file);

Ok(serde_json::from_reader(reader).unwrap())
}
Ok(serde_json::from_reader(reader).unwrap())
} else {
let schema_file = File::create(&local_schema)?;
let schema = ecosystem::get_schema().await?;

false => {
let schema_file = File::create(&local_schema)?;
let schema = ecosystem::get_schema().await?;
let schema_writer = BufWriter::new(&schema_file);
serde_json::to_writer_pretty(schema_writer, &schema).unwrap();

let schema_writer = BufWriter::new(&schema_file);
serde_json::to_writer_pretty(schema_writer, &schema).unwrap();

Ok(schema)
}
Ok(schema)
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/game/import/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ pub mod steam;

use std::path::{Path, PathBuf};

use super::ecosystem;
use super::error::GameError;
use super::registry::{ActiveDistribution, GameData};
use crate::error::Error;
use crate::game::import::ea::EaImporter;
use crate::game::import::egs::EgsImporter;
use crate::game::import::gamepass::GamepassImporter;
use crate::game::import::steam::SteamImporter;
use crate::ts::v1::models::ecosystem::GameDef;
use crate::ts::v1::{ecosystem, models::ecosystem::GameDefPlatform};
use crate::ts::v1::models::ecosystem::{ GameDef, GameDefPlatform };

pub trait GameImporter {
fn construct(self: Box<Self>, base: ImportBase) -> Result<GameData, Error>;
Expand All @@ -39,7 +39,7 @@ impl ImportBase {
pub async fn new(game_id: &str) -> Result<Self, Error> {
let game_def = ecosystem::get_schema()
.await
.map_err(|_| GameError::EcosystemSchema)?
.unwrap()
.games
.get(game_id)
.ok_or_else(|| GameError::BadGameId(game_id.into()))?
Expand Down
20 changes: 17 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
use std::path::PathBuf;

use clap::Parser;
use cli::InitSubcommand;
use cli::{ExternSubcommand, InitSubcommand};
use colored::Colorize;
use directories::BaseDirs;
use error::{IoError, Error};
use game::import::GameImporter;
use game::import::{select_importer, GameImporter};

Check warning

Code scanning / clippy

unused import: select_importer Warning

unused import: select\_importer
use once_cell::sync::Lazy;
use project::error::ProjectError;
use project::ProjectKind;
Expand Down Expand Up @@ -359,7 +359,21 @@
server::spawn(read, write, &project_path).await?;

Ok(())
},
}

Commands::Extern { command } => {
match command {
ExternSubcommand::GameData { game_id } => {
let base = ImportBase::new(&game_id).await?;
let game_data = import::select_importer(&base)?
.construct(base)?;

println!("{}", serde_json::to_string_pretty(&game_data.active_distribution)?);
}
}

Ok(())
}
};

test
Expand Down
23 changes: 12 additions & 11 deletions src/package/install/legacy_compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,17 @@ async fn init_installer_map() -> Result<HashMap<String, String>, Error> {
("northstar", "metherul-Northstar_Installer"),
]);

let installer_map = schema
.games
.into_iter()
.filter_map(|(_, def)| def.r2modman)
.flat_map(|def| def.mod_loader_packages)
.filter_map(|loader| match map.get(loader.loader.as_str()) {
Some(installer) => Some((loader.package_id, installer.to_string())),
None => None,
})
.collect::<HashMap<_, _>>();
// let installer_map = schema
// .games
// .into_iter()
// .filter_map(|(_, def)| def.r2modman)
// .flat_map(|def| schema.modloader_packages)
// .filter_map(|loader| match map.get(loader.loader.as_str()) {
// Some(installer) => Some((loader.package_id, installer.to_string())),
// None => None,
// })
// .collect::<HashMap<_, _>>();

Ok(installer_map)
// Shim out until we re-integrate the moved modloader_packages ecosystem field.
Ok(HashMap::new())
}
16 changes: 8 additions & 8 deletions src/ts/v1/models/ecosystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub struct EcosystemSchema {
pub schema_version: Version,
pub games: HashMap<String, GameDef>,
pub communities: HashMap<String, SchemaCommunity>,
pub modloader_packages: Vec<R2MMModLoaderPackage>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
Expand All @@ -34,7 +35,7 @@ pub struct GameDefMeta {
#[serde(tag = "platform")]
#[serde(rename_all = "kebab-case")]
pub enum GameDefPlatform {
#[serde(rename = "egs")]
#[serde(rename = "epic-games-store")]
EpicGames {
identifier: String,
},
Expand All @@ -51,6 +52,7 @@ pub enum GameDefPlatform {
SteamDirect {
identifier: String,
},
#[serde(rename = "oculus-store")]
Oculus,
Other,
}
Expand All @@ -60,7 +62,7 @@ impl GameDefPlatform {
/// the ecosystem schema, preferably as a compile time check.
pub fn ident_from_name<'a>(&'a self, name: &str) -> Option<&'a str> {
match self {
GameDefPlatform::EpicGames { identifier } if name == "egs" => Some(identifier),
GameDefPlatform::EpicGames { identifier } if name == "epic-games-store" => Some(identifier),
GameDefPlatform::GamePass { identifier } if name == "gamepass" => Some(identifier),
GameDefPlatform::Origin { identifier } if name == "origin" || name == "ea" => {
Some(identifier)
Expand All @@ -76,11 +78,11 @@ impl GameDefPlatform {
pub fn get_platform_names(&self) -> Vec<&'static str> {
vec![
"origin",
"egs",
"epic-games-store",
"gamepass",
"steam",
"steam-direct",
"oculus",
"oculus-store",
"other",
]
}
Expand All @@ -93,14 +95,12 @@ pub struct GameDefR2MM {
pub data_folder_name: String,
pub settings_identifier: String,
pub package_index: String,
pub exclusions_url: String,
pub steam_folder_name: String,
pub exe_names: Vec<String>,
pub game_instancetype: String,
pub game_instance_type: String,
pub game_selection_display_mode: String,
pub mod_loader_packages: Vec<R2MMModLoaderPackage>,
pub install_rules: Vec<R2MMInstallRule>,
pub relative_file_exclusions: Vec<String>,
pub relative_file_exclusions: Option<Vec<String>>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
Expand Down
Loading