use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "snake_case")] pub enum VersionType { Release, Snapshot, OldAlpha, OldBeta, } impl VersionType { pub fn as_str(&self) -> &'static str { match self { VersionType::Release => "release", VersionType::Snapshot => "snapshot", VersionType::OldAlpha => "old_alpha", VersionType::OldBeta => "old_beta", } } } #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub struct Version { pub id: String, #[serde(rename = "type")] pub type_: VersionType, pub url: String, pub time: DateTime, pub release_time: DateTime, } #[derive(Deserialize, Debug)] pub struct LatestVersion { pub release: String, pub snapshot: String, } #[derive(Deserialize, Debug)] pub struct VersionManifest { pub latest: LatestVersion, pub versions: Vec, } pub async fn fetch_version_manifest() -> Result { reqwest::get("https://launchermeta.mojang.com/mc/game/version_manifest.json") .await? .json() .await } #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub struct AssetIndex { pub id: String, pub sha1: String, pub size: u32, pub total_size: u32, pub url: String, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash)] #[serde(rename_all = "snake_case")] pub enum DownloadType { Client, ClientMappings, Server, ServerMappings, WindowsServer, } #[derive(Serialize, Deserialize, Debug)] pub struct Download { pub sha1: String, pub size: u32, pub url: String, } #[derive(Serialize, Deserialize, Debug)] pub struct LibraryDownload { pub path: String, pub sha1: String, pub size: u32, pub url: String, } #[derive(Serialize, Deserialize, Debug)] pub struct LibraryDownloads { pub artifact: Option, pub classifiers: Option>, } #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "snake_case")] pub enum RuleAction { Allow, Disallow, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash)] #[serde(rename_all = "snake_case")] pub enum Os { Osx, Windows, Linux, Unknown, } #[derive(Serialize, Deserialize, Debug)] pub struct OsRule { pub name: Option, pub version: Option, pub arch: Option, } #[derive(Serialize, Deserialize, Debug)] pub struct FeatureRule { pub is_demo_user: Option, pub has_demo_resolution: Option, } #[derive(Serialize, Deserialize, Debug)] pub struct Rule { pub action: RuleAction, pub os: Option, pub features: Option, } #[derive(Serialize, Deserialize, Debug)] pub struct LibraryExtract { pub exclude: Option>, } #[derive(Serialize, Deserialize, Debug)] pub struct Library { pub downloads: LibraryDownloads, pub extract: Option, pub name: String, pub natives: Option>, pub rules: Option>, } #[derive(Serialize, Deserialize, Debug)] #[serde(untagged)] pub enum ArgumentValue { Single(String), Many(Vec), } #[derive(Serialize, Deserialize, Debug)] #[serde(untagged)] pub enum Argument { Normal(String), Ruled { rules: Vec, value: ArgumentValue, }, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash)] #[serde(rename_all = "snake_case")] pub enum ArgumentType { Game, Jvm, } #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub struct VersionInfo { pub arguments: Option>>, pub asset_index: AssetIndex, pub assets: String, pub downloads: HashMap, pub id: String, pub libraries: Vec, pub main_class: String, pub minecraft_arguments: Option, pub minimum_launcher_version: u32, pub release_time: DateTime, pub time: DateTime, #[serde(rename = "type")] pub type_: VersionType, } pub async fn fetch_version_info(version: &Version) -> Result { reqwest::get(&version.url).await?.json().await } #[derive(Serialize, Deserialize, Debug)] pub struct Asset { pub hash: String, pub size: u32, } #[derive(Serialize, Deserialize, Debug)] pub struct AssetsIndex { pub objects: HashMap, } pub async fn fetch_assets_index(version: &VersionInfo) -> Result { reqwest::get(&version.asset_index.url).await?.json().await }