From 7960fdcbff44b4cd858203562a8f613efe39eb8d Mon Sep 17 00:00:00 2001 From: bigfoot547 Date: Tue, 4 Feb 2025 22:14:54 -0600 Subject: get started on cli --- Cargo.lock | 14 +++++++++++- ozone-cli/Cargo.toml | 3 +-- ozone-cli/src/cli.rs | 46 ++++++++++++++++++++++++++++++++++++++++ ozone-cli/src/main.rs | 47 ++++++++++++++++++++++++++++++++++------- ozone-cli/work/ozone.json | 24 +++++++++++++++++++++ ozone/src/launcher.rs | 5 ++++- ozone/src/launcher/constants.rs | 6 ++---- ozone/src/launcher/runner.rs | 1 + ozone/src/launcher/settings.rs | 13 ++++++++++-- 9 files changed, 141 insertions(+), 18 deletions(-) create mode 100644 ozone-cli/src/cli.rs create mode 100644 ozone-cli/work/ozone.json diff --git a/Cargo.lock b/Cargo.lock index d44df77..3ea5d97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -811,6 +811,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "769b0145982b4b48713e01ec42d61614425f27b7058bda7180a3a41f30104796" dependencies = [ "clap_builder", + "clap_derive", ] [[package]] @@ -825,6 +826,18 @@ dependencies = [ "strsim", ] +[[package]] +name = "clap_derive" +version = "4.5.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "clap_lex" version = "0.7.4" @@ -3505,7 +3518,6 @@ dependencies = [ "log", "ozone", "simple_logger", - "sysinfo", "tokio", ] diff --git a/ozone-cli/Cargo.toml b/ozone-cli/Cargo.toml index e793eaa..dbbda5d 100644 --- a/ozone-cli/Cargo.toml +++ b/ozone-cli/Cargo.toml @@ -4,9 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -sysinfo = { version = "0.33.1", features = ["system", "multithread"] } ozone = { path = "../ozone" } tokio = { version = "1.43.0", features = ["rt", "rt-multi-thread", "macros"] } simple_logger = { version = "5.0.0", features = ["colors"] } log = "0.4.25" -clap = "4.5.27" +clap = { version = "4.5.27", features = ["derive", "cargo"] } diff --git a/ozone-cli/src/cli.rs b/ozone-cli/src/cli.rs new file mode 100644 index 0000000..d288e3c --- /dev/null +++ b/ozone-cli/src/cli.rs @@ -0,0 +1,46 @@ +use std::path::PathBuf; +use clap::{Args, Parser, Subcommand}; + +#[derive(Subcommand, Debug)] +pub enum ProfileCommand { + Select, + Create, + List +} + +#[derive(Args, Debug)] +pub struct ProfileArgs { + #[command(subcommand)] + subcmd: Option +} + +impl ProfileArgs { + pub fn take_command(&mut self) -> ProfileCommand { + self.subcmd.take().unwrap_or(ProfileCommand::List) + } +} + +#[derive(Subcommand, Debug)] +pub enum RootCommand { + Profile(ProfileArgs), + Instance, + +} + +#[derive(Parser, Debug)] +#[clap(version)] +pub struct Cli { + /// Run the launcher in offline mode. The launcher will not attempt to make any requests using + /// the network. The launcher _will_ verify the integrity of files required to launch the game, + /// and refuse to launch the game with an error if it must download a file. + #[arg(long, global = true)] + pub offline: bool, + + /// Directory which the launcher will perform its work in. Defaults to an application-specific + /// directory based on your OS. + #[arg(long, global = true, value_hint = clap::ValueHint::DirPath)] + pub home: Option, + + #[command(subcommand)] + pub subcmd: RootCommand +} diff --git a/ozone-cli/src/main.rs b/ozone-cli/src/main.rs index a17979e..b449209 100644 --- a/ozone-cli/src/main.rs +++ b/ozone-cli/src/main.rs @@ -1,16 +1,49 @@ +mod cli; + use std::error::Error; +use std::path::PathBuf; +use std::process::{ExitCode, ExitStatus}; use log::{error, info}; +use clap::{Args, Parser, Subcommand}; use ozone::launcher::{Launcher, Settings}; +use crate::cli::{Cli, ProfileCommand, RootCommand}; + +async fn main_inner(cli: Cli) -> Result> { + let Some(home) = cli.home.or_else(|| Launcher::sensible_home()) else { + error!("Could not choose a launcher home directory. Please choose one with `--home'."); + Ok(ExitCode::FAILURE) // we print our own error message + }; + + info!("Sensible home could be {home:?}"); + let settings = Settings::load(home.join("ozone.json")).await?; + settings.save().await?; + + match cli.subcmd { + RootCommand::Profile(mut p) => match p.take_command() { + ProfileCommand::List => { + + } + } + } + + Ok(ExitCode::SUCCESS) +} + #[tokio::main] -async fn main() -> Result<(), Box> { +async fn main() -> ExitCode { simple_logger::SimpleLogger::new().env().init().unwrap(); - info!("Sensible home could be {:?}", Launcher::sensible_home()); - let settings = Settings::load("./work/ozone.json").await?; - settings.save().await?; + let arg = dbg!(Cli::parse()); - let launcher = Launcher::new("./work", true).await?; + main_inner(arg).await.unwrap_or_else(|e| { + error!("Launcher initialization error:"); + error!("{e}"); + + ExitCode::FAILURE + }) + + /*let launcher = Launcher::new("./work", true).await?; let profile = settings.get_profile("default").unwrap(); @@ -22,7 +55,5 @@ async fn main() -> Result<(), Box> { dbg!(&launch); info!("ok"); - ozone::launcher::run_the_game(&launch)?; - - Ok(()) + ozone::launcher::run_the_game(&launch)?;*/ } diff --git a/ozone-cli/work/ozone.json b/ozone-cli/work/ozone.json new file mode 100644 index 0000000..f1ed208 --- /dev/null +++ b/ozone-cli/work/ozone.json @@ -0,0 +1,24 @@ +{ + "profiles": { + "default": { + "game_version": "latest_release", + "java_runtime": null, + "instance": "default", + "jvm_arguments": [ + "-Xmx2G", + "-XX:+UnlockExperimentalVMOptions", + "-XX:+UseG1GC", + "-XX:G1NewSizePercent=20", + "-XX:G1ReservePercent=20", + "-XX:MaxGCPauseMillis=50", + "-XX:G1HeapRegionSize=32M" + ] + } + }, + "instances": { + "default": { + "path": "default" + } + }, + "client_id": "8e1cd116-9100-46cb-86b8-1a4ad54c5cbe" +} \ No newline at end of file diff --git a/ozone/src/launcher.rs b/ozone/src/launcher.rs index 8d22d3b..8ee532b 100644 --- a/ozone/src/launcher.rs +++ b/ozone/src/launcher.rs @@ -28,6 +28,7 @@ use reqwest::Client; use sysinfo::System; use tokio::{fs, io}; use tokio_stream::wrappers::ReadDirStream; +use uuid::Uuid; use download::{MultiDownloader, VerifiedDownload}; use rules::{CompatCheck, IncompatibleError}; use version::{VersionList, VersionResolveError, VersionResult}; @@ -199,6 +200,7 @@ impl Error for LaunchError { struct LaunchInfo<'l, F: FeatureMatcher> { launcher: &'l Launcher, feature_matcher: &'l F, + client_id: Uuid, asset_index_name: Option, classpath: String, @@ -330,7 +332,7 @@ impl Launcher { * - launch game using JNI * - auth */ - pub async fn prepare_launch(&self, profile: &Profile, instance: &Instance) -> Result { + pub async fn prepare_launch(&self, profile: &Profile, instance: &Instance, client_id: Uuid) -> Result { let start = Instant::now(); let feature_matcher = ProfileFeatureMatcher { profile }; let version_id = profile.get_version(); @@ -518,6 +520,7 @@ impl Launcher { let info = LaunchInfo { launcher: self, feature_matcher: &feature_matcher, + client_id, asset_index_name: asset_idx_name.map(|s| s.to_owned()), classpath, diff --git a/ozone/src/launcher/constants.rs b/ozone/src/launcher/constants.rs index d370f32..4506ab5 100644 --- a/ozone/src/launcher/constants.rs +++ b/ozone/src/launcher/constants.rs @@ -1,10 +1,8 @@ use lazy_static::lazy_static; use regex::Regex; -//pub const URL_VERSION_MANIFEST: &str = "https://piston-meta.mojang.com/mc/game/version_manifest_v2.json"; -pub const URL_VERSION_MANIFEST: &str = "https://meta.omniarchive.uk/v1/manifest.json"; -//pub const URL_RESOURCE_BASE: &str = "https://resources.download.minecraft.net/"; -pub const URL_RESOURCE_BASE: &str = "https://meta.omniarchive.uk/resources/"; +pub const URL_VERSION_MANIFEST: &str = "https://piston-meta.mojang.com/mc/game/version_manifest_v2.json"; +pub const URL_RESOURCE_BASE: &str = "https://resources.download.minecraft.net/"; pub const URL_JRE_MANIFEST: &str = "https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"; pub const NATIVES_PREFIX: &str = "natives-"; diff --git a/ozone/src/launcher/runner.rs b/ozone/src/launcher/runner.rs index 1dc0761..7c1a903 100644 --- a/ozone/src/launcher/runner.rs +++ b/ozone/src/launcher/runner.rs @@ -33,6 +33,7 @@ impl<'rep, F: FeatureMatcher> SubFunc<'rep> for LaunchArgSub<'rep, '_, F> { "auth_xuid" => Some(Cow::Borrowed("0000000000000000")), // TODO "classpath" => Some(Cow::Borrowed(self.0.classpath.as_str())), "classpath_separator" => Some(Cow::Borrowed(PATH_SEP)), + "clientid" | "client_id" => Some(Cow::Owned(self.0.client_id.to_string())), "game_assets" => self.0.virtual_assets_path.as_ref() .map(|s| s.as_path().as_java_path().to_string_lossy()), "game_directory" => Some(self.0.instance_home.as_java_path().to_string_lossy()), diff --git a/ozone/src/launcher/settings.rs b/ozone/src/launcher/settings.rs index 6295433..5e15604 100644 --- a/ozone/src/launcher/settings.rs +++ b/ozone/src/launcher/settings.rs @@ -8,12 +8,16 @@ use serde::{Deserialize, Serialize}; use tokio::{fs, io}; use tokio::fs::File; use tokio::io::AsyncWriteExt; +use uuid::Uuid; use super::constants; #[derive(Debug, Clone, Serialize, Deserialize)] struct SettingsInner { profiles: HashMap, - instances: HashMap + instances: HashMap, + + #[serde(default = "uuid::Uuid::new_v4")] + client_id: Uuid } pub struct Settings { @@ -52,7 +56,8 @@ impl Default for SettingsInner { fn default() -> Self { SettingsInner { instances: [(String::from(constants::DEF_INSTANCE_NAME), PathBuf::from(constants::DEF_INSTANCE_NAME).into())].into_iter().collect(), - profiles: [(String::from(constants::DEF_PROFILE_NAME), Profile::new(constants::DEF_INSTANCE_NAME))].into_iter().collect() + profiles: [(String::from(constants::DEF_PROFILE_NAME), Profile::new(constants::DEF_INSTANCE_NAME))].into_iter().collect(), + client_id: Uuid::new_v4() } } } @@ -124,6 +129,10 @@ impl Settings { pub fn get_instance_for(&self, profile: &Profile) -> &Instance { self.inner.instances.get(&profile.instance).unwrap() } + + pub fn get_client_id(&self) -> Uuid { + self.inner.client_id + } } #[derive(Deserialize, Serialize, Debug, Clone)] -- cgit v1.2.3-70-g09d2