parent
23d5e8cc29
commit
220a2b4553
@ -0,0 +1,39 @@
|
|||||||
|
pub mod manifest;
|
||||||
|
|
||||||
|
pub struct MinecraftVersion {
|
||||||
|
pub version_json: manifest::VersionJson,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_latest_version() -> Result<MinecraftVersion, ureq::Error> {
|
||||||
|
let response = ureq::get("https://launchermeta.mojang.com/mc/game/version_manifest.json").call();
|
||||||
|
let version_manifest = response.unwrap().into_string().unwrap();
|
||||||
|
let version_manifest: manifest::VersionManifest = serde_json::from_str(&version_manifest).unwrap();
|
||||||
|
let latest_release = &version_manifest.latest.release;
|
||||||
|
fetch_version(latest_release)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fetch_version(version_name: &str) -> Result<MinecraftVersion, ureq::Error> {
|
||||||
|
let response = ureq::get("https://launchermeta.mojang.com/mc/game/version_manifest.json").call();
|
||||||
|
let version_manifest = response.unwrap().into_string().unwrap();
|
||||||
|
let version_manifest: manifest::VersionManifest = serde_json::from_str(&version_manifest).unwrap();
|
||||||
|
let selected_version = version_manifest.versions.iter().find(
|
||||||
|
|version| version.id.as_str() == version_name)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let response = ureq::get(&selected_version.url).call();
|
||||||
|
let version_json = response.unwrap().into_string().unwrap();
|
||||||
|
let version_json: manifest::VersionJson = serde_json::from_str(&version_json).unwrap();
|
||||||
|
Ok(MinecraftVersion { version_json: version_json })
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MinecraftVersion {
|
||||||
|
pub fn get_asset_index(&self) -> Result<manifest::AssetIndex, ureq::Error> {
|
||||||
|
let response = ureq::get(&self.version_json.asset_index.url).call();
|
||||||
|
let asset_index = response.unwrap().into_string().unwrap();
|
||||||
|
let asset_index: manifest::AssetIndex = serde_json::from_str(&asset_index).unwrap();
|
||||||
|
Ok(asset_index)
|
||||||
|
}
|
||||||
|
pub fn get_libraries_for_os(&self, os: &str) -> Vec<manifest::Library> {
|
||||||
|
todo!("Stub; Needs filtering by os name, taking into account both the blacklist and whitelist");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,232 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_with::skip_serializing_none;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct VersionManifest {
|
||||||
|
pub latest: Latest,
|
||||||
|
pub versions: Vec<Version>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Latest {
|
||||||
|
pub release: String,
|
||||||
|
pub snapshot: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Version {
|
||||||
|
pub id: String,
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub type_: String,
|
||||||
|
pub url: String,
|
||||||
|
pub time: String,
|
||||||
|
#[serde(rename = "releaseTime")]
|
||||||
|
pub release_time: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[skip_serializing_none]
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct AssetIndexUrl {
|
||||||
|
pub id: String,
|
||||||
|
pub sha1: String,
|
||||||
|
pub size: u64,
|
||||||
|
pub url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[skip_serializing_none]
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct VersionJson {
|
||||||
|
pub arguments: Option<Arguments>,
|
||||||
|
#[serde(rename = "assetIndex")]
|
||||||
|
pub asset_index: AssetIndexUrl,
|
||||||
|
pub assets: String,
|
||||||
|
#[serde(rename = "complianceLevel")]
|
||||||
|
pub compliance_level: Option<u32>,
|
||||||
|
pub downloads: Downloads,
|
||||||
|
pub id: String,
|
||||||
|
#[serde(rename = "javaVersion")]
|
||||||
|
pub java_version: Option<JavaVersion>,
|
||||||
|
pub libraries: Vec<Library>,
|
||||||
|
pub logging: Option<Logging>,
|
||||||
|
#[serde(rename = "mainClass")]
|
||||||
|
pub main_class: String,
|
||||||
|
#[serde(rename = "minimumLauncherVersion")]
|
||||||
|
pub minimum_launcher_version: u32,
|
||||||
|
#[serde(rename = "releaseTime")]
|
||||||
|
pub release_time: String,
|
||||||
|
pub time: String,
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub type_: String,
|
||||||
|
#[serde(rename = "minecraftArguments")]
|
||||||
|
pub minecraft_arguments: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Arguments {
|
||||||
|
pub game: Option<Vec<GameArgument>>,
|
||||||
|
pub jvm: Option<Vec<JVMArgument>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum GameArgument {
|
||||||
|
String(String),
|
||||||
|
Complex(GameArgumentComplex),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct GameArgumentComplex {
|
||||||
|
pub rules: Option<Vec<Rule>>,
|
||||||
|
pub value: ValueType,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum JVMArgument {
|
||||||
|
String(String),
|
||||||
|
Complex(JVMArgumentComplex),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct JVMArgumentComplex {
|
||||||
|
pub rules: Option<Vec<Rule>>,
|
||||||
|
pub value: ValueType,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum ValueType {
|
||||||
|
String(String),
|
||||||
|
VecString(Vec<String>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Rule {
|
||||||
|
pub action: String,
|
||||||
|
pub os: Option<OS>,
|
||||||
|
pub features: Option<HashMap<String, bool>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct OS {
|
||||||
|
pub arch: Option<String>,
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub version: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct AssetIndex {
|
||||||
|
pub objects: HashMap<String, AssetObject>,
|
||||||
|
#[serde(rename = "virtual")]
|
||||||
|
pub virtual_: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct AssetObject {
|
||||||
|
pub hash: String,
|
||||||
|
pub size: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Downloads {
|
||||||
|
pub client: DownloadFile,
|
||||||
|
#[serde(rename = "client_mappings")]
|
||||||
|
pub client_mappings: Option<DownloadFile>,
|
||||||
|
pub server: DownloadFile,
|
||||||
|
#[serde(rename = "server_mappings")]
|
||||||
|
pub server_mappings: Option<DownloadFile>,
|
||||||
|
#[serde(rename = "windows_server")]
|
||||||
|
pub windows_server: Option<DownloadFile>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct DownloadFile {
|
||||||
|
pub sha1: String,
|
||||||
|
pub size: u64,
|
||||||
|
pub url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct JavaVersion {
|
||||||
|
pub component: String,
|
||||||
|
#[serde(rename = "majorVersion")]
|
||||||
|
pub major_version: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Library {
|
||||||
|
pub downloads: LibraryDownloads,
|
||||||
|
pub name: String,
|
||||||
|
pub rules: Option<Vec<Rule>>,
|
||||||
|
pub extract: Option<Extract>,
|
||||||
|
pub natives: Option<Natives>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum LibraryDownloads {
|
||||||
|
Artifact(LibraryArtifact),
|
||||||
|
Classifiers(LibraryClassifiers),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct LibraryArtifact {
|
||||||
|
pub artifact: LibraryFile,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct LibraryClassifiers {
|
||||||
|
pub classifiers: Classifiers,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Classifiers {
|
||||||
|
#[serde(rename = "natives-linux")]
|
||||||
|
pub natives_linux: Option<LibraryFile>,
|
||||||
|
#[serde(rename = "natives-osx")]
|
||||||
|
pub natives_osx: Option<LibraryFile>,
|
||||||
|
#[serde(rename = "natives-windows")]
|
||||||
|
pub natives_windows: Option<LibraryFile>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct LibraryFile {
|
||||||
|
pub path: String,
|
||||||
|
pub sha1: String,
|
||||||
|
pub size: u64,
|
||||||
|
pub url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Extract {
|
||||||
|
pub exclude: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Natives {
|
||||||
|
pub linux: String,
|
||||||
|
pub osx: String,
|
||||||
|
pub windows: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Logging {
|
||||||
|
pub client: LoggingClient,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct LoggingClient {
|
||||||
|
pub argument: String,
|
||||||
|
pub file: LoggingFile,
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub type_: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct LoggingFile {
|
||||||
|
pub id: String,
|
||||||
|
pub sha1: String,
|
||||||
|
pub size: u64,
|
||||||
|
pub url: String,
|
||||||
|
}
|
@ -0,0 +1,119 @@
|
|||||||
|
use mclaunch::manifest::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_arguments() {
|
||||||
|
let src = r#"
|
||||||
|
{
|
||||||
|
"game": [
|
||||||
|
{
|
||||||
|
"rules": [
|
||||||
|
],
|
||||||
|
"value": [
|
||||||
|
"--quickPlayRealms",
|
||||||
|
"${quickPlayRealms}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"jvm": [
|
||||||
|
]
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
let arguments: Arguments = serde_json::from_str(src).unwrap();
|
||||||
|
println!("{:#?}", arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_basic_decode() {
|
||||||
|
// Grab minecraft version manifest
|
||||||
|
let response = ureq::get("https://launchermeta.mojang.com/mc/game/version_manifest.json").call();
|
||||||
|
let version_manifest = response.unwrap().into_string().unwrap();
|
||||||
|
// Deserialize the version manifest
|
||||||
|
let version_manifest: VersionManifest = serde_json::from_str(&version_manifest).unwrap();
|
||||||
|
// Print the version manifest
|
||||||
|
println!("{:#?}", version_manifest);
|
||||||
|
// fetch the latest release version
|
||||||
|
let latest_release = &version_manifest.latest.release;
|
||||||
|
// Print the latest release version
|
||||||
|
println!("Latest release version: {}", latest_release);
|
||||||
|
// Fetch the Version struct for the latest release version
|
||||||
|
let latest_release_version = version_manifest.versions.iter().find(
|
||||||
|
|version| version.id.as_str() == latest_release.as_str())
|
||||||
|
.unwrap();
|
||||||
|
// Print the latest release version struct
|
||||||
|
println!("{:#?}", latest_release_version);
|
||||||
|
|
||||||
|
// Fetch the version manifest for the latest release version
|
||||||
|
let response = ureq::get(&latest_release_version.url).call();
|
||||||
|
let version_json = response.unwrap().into_string().unwrap();
|
||||||
|
// Print the version manifest for the latest release version
|
||||||
|
println!("{}", version_json);
|
||||||
|
// Deserialize the version manifest for the latest release version
|
||||||
|
let version_json: VersionJson = serde_json::from_str(&version_json).unwrap();
|
||||||
|
// Print the version manifest for the latest release version
|
||||||
|
println!("{:#?}", version_json);
|
||||||
|
// Grab the asset index url
|
||||||
|
let asset_index_url = &version_json.asset_index.url;
|
||||||
|
// Print the asset index url
|
||||||
|
println!("Asset index url: {}", asset_index_url);
|
||||||
|
// Fetch the asset index
|
||||||
|
let response = ureq::get(asset_index_url).call();
|
||||||
|
let asset_index = response.unwrap().into_string().unwrap();
|
||||||
|
// Print the asset index
|
||||||
|
println!("{}", asset_index);
|
||||||
|
// Deserialize the asset index
|
||||||
|
let asset_index: AssetIndex = serde_json::from_str(&asset_index).unwrap();
|
||||||
|
// Print the asset index
|
||||||
|
println!("{:#?}", asset_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_164_decode() {
|
||||||
|
// Grab minecraft version manifest
|
||||||
|
let response = ureq::get("https://launchermeta.mojang.com/mc/game/version_manifest.json").call();
|
||||||
|
let version_manifest = response.unwrap().into_string().unwrap();
|
||||||
|
// Deserialize the version manifest
|
||||||
|
let version_manifest: VersionManifest = serde_json::from_str(&version_manifest).unwrap();
|
||||||
|
// Print the version manifest
|
||||||
|
println!("{:#?}", version_manifest);
|
||||||
|
// fetch the 1.6.4 version
|
||||||
|
let version_164 = version_manifest.versions.iter().find(
|
||||||
|
|version| version.id.as_str() == "1.6.4")
|
||||||
|
.unwrap();
|
||||||
|
// Print the 1.6.4 version
|
||||||
|
println!("{:#?}", version_164);
|
||||||
|
|
||||||
|
// Fetch the version manifest for the 1.6.4 version
|
||||||
|
let response = ureq::get(&version_164.url).call();
|
||||||
|
let version_json = response.unwrap().into_string().unwrap();
|
||||||
|
// Print the version manifest for the 1.6.4 version
|
||||||
|
println!("{}", version_json);
|
||||||
|
// Deserialize the version manifest for the 1.6.4 version
|
||||||
|
let version_json: VersionJson = serde_json::from_str(&version_json).unwrap();
|
||||||
|
// Print the version manifest for the 1.6.4 version
|
||||||
|
println!("{:#?}", version_json);
|
||||||
|
// Grab the asset index url
|
||||||
|
let asset_index_url = &version_json.asset_index.url;
|
||||||
|
// Print the asset index url
|
||||||
|
println!("Asset index url: {}", asset_index_url);
|
||||||
|
// Fetch the asset index
|
||||||
|
let response = ureq::get(asset_index_url).call();
|
||||||
|
let asset_index = response.unwrap().into_string().unwrap();
|
||||||
|
// Print the asset index
|
||||||
|
println!("{}", asset_index);
|
||||||
|
// Deserialize the asset index
|
||||||
|
let asset_index: AssetIndex = serde_json::from_str(&asset_index).unwrap();
|
||||||
|
// Print the asset index
|
||||||
|
println!("{:#?}", asset_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_latest_decode() {
|
||||||
|
let latest = mclaunch::get_latest_version().unwrap();
|
||||||
|
let _asset_index = latest.get_asset_index().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_164_decode_latest() {
|
||||||
|
let version_164 = mclaunch::fetch_version("1.6.4").unwrap();
|
||||||
|
let _asset_index = version_164.get_asset_index().unwrap();
|
||||||
|
}
|
Loading…
Reference in new issue