You've already forked AstralRinth
forked from didirus/AstralRinth
Downloading launcher files
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/theseus.iml" filepath="$PROJECT_DIR$/.idea/theseus.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
49
.idea/theseus.iml
generated
Normal file
49
.idea/theseus.iml
generated
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/theseus/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/theseus_cli/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/memchr-f931d8711453d858/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/proc-macro2-9fe81105fb85f6f3/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/semver-bafb0545aca51a71/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/syn-4186910aa7ddbfea/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/bitflags-88b50a288ea9b589/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/encoding_rs-aeb75e3d7246cd68/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/futures-channel-0dafdf8e6c56074a/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/futures-core-282be4c3d523964b/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/futures-task-0e283041f0d04d9b/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/futures-util-53aed327071491e2/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/httparse-16fab0b2d90ac92a/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/indexmap-b9724370d61f58d6/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/libc-d1245e7816855bad/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/log-655c062cb95acdc8/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/native-tls-4354688a3ac4c342/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/num-integer-243211f2ff028008/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/num-traits-267e007703d2b65d/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/openssl-4b1b3d11a2faa97c/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/openssl-sys-a24d131c4a98488f/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/ryu-3b42f9ed428b96b3/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/serde-4a54573c5a9c851c/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/serde-a78322380378b8a8/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/serde_derive-24d0f79641168b3d/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/serde_json-e22a1220ea14f789/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/syn-3c24ac6a6f9c5ce5/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/tokio-42e357298afc1829/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/futures-channel-aaca776527d6f74c/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/futures-macro-8bed64c7e4137015/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/futures-task-99072bb77352f68a/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/futures-util-84b73402819de30c/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/proc-macro-hack-a3cb2722e7116198/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/proc-macro-nested-c16c856e8deac6ce/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/bzip2-sys-75559f3495f10aba/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/crc32fast-f112d4af2349618a/out" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/target/debug/build/miniz_oxide-d683d4a97661215e/out" isTestSource="false" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
1298
Cargo.lock
generated
Normal file
1298
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
6
Cargo.toml
Normal file
6
Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[workspace]
|
||||||
|
|
||||||
|
members = [
|
||||||
|
"theseus",
|
||||||
|
"theseus_cli"
|
||||||
|
]
|
||||||
24
theseus/Cargo.toml
Normal file
24
theseus/Cargo.toml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
[package]
|
||||||
|
name = "theseus"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Jai A <jaiagr+gpg@pm.me>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
thiserror = "1.0"
|
||||||
|
|
||||||
|
reqwest = { version = "0.11", features = ["json"] }
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0"
|
||||||
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
|
uuid = "0.8"
|
||||||
|
bytes = "1"
|
||||||
|
zip = "0.5"
|
||||||
|
|
||||||
|
regex = "1.5"
|
||||||
|
lazy_static = "1.4"
|
||||||
|
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
futures = "0.3"
|
||||||
1
theseus/src/launcher/auth.rs
Normal file
1
theseus/src/launcher/auth.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
222
theseus/src/launcher/download.rs
Normal file
222
theseus/src/launcher/download.rs
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
use crate::launcher::meta::{
|
||||||
|
Asset, AssetIndex, AssetsIndex, DownloadType, Library, Os, RuleAction, VersionInfo,
|
||||||
|
};
|
||||||
|
use futures::future;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{BufReader, Write};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
pub async fn download_client(client_path: &Path, version_info: &VersionInfo) {
|
||||||
|
let client = download_file(
|
||||||
|
&version_info
|
||||||
|
.downloads
|
||||||
|
.get(&DownloadType::Client)
|
||||||
|
.unwrap()
|
||||||
|
.url,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
save_file(
|
||||||
|
&*client_path
|
||||||
|
.join(&version_info.id)
|
||||||
|
.join(format!("{}.jar", &version_info.id)),
|
||||||
|
&client,
|
||||||
|
);
|
||||||
|
save_file(
|
||||||
|
&*client_path
|
||||||
|
.join(&version_info.id)
|
||||||
|
.join(format!("{}.json", &version_info.id)),
|
||||||
|
&bytes::Bytes::from(serde_json::to_string(version_info).unwrap()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn download_assets(
|
||||||
|
assets_path: &Path,
|
||||||
|
legacy_path: Option<&Path>,
|
||||||
|
meta: AssetIndex,
|
||||||
|
index: &AssetsIndex,
|
||||||
|
) {
|
||||||
|
save_file(
|
||||||
|
&*assets_path
|
||||||
|
.join("indexes")
|
||||||
|
.join(format!("{}.json", meta.id)),
|
||||||
|
&bytes::Bytes::from(serde_json::to_string(index).unwrap()),
|
||||||
|
);
|
||||||
|
|
||||||
|
future::join_all(
|
||||||
|
index
|
||||||
|
.objects
|
||||||
|
.iter()
|
||||||
|
.map(|x| download_asset(assets_path, legacy_path, x.0, x.1)),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn download_asset(
|
||||||
|
assets_path: &Path,
|
||||||
|
legacy_path: Option<&Path>,
|
||||||
|
name: &String,
|
||||||
|
asset: &Asset,
|
||||||
|
) {
|
||||||
|
let sub_hash = &&asset.hash[..2];
|
||||||
|
|
||||||
|
let resource = download_file(&format!(
|
||||||
|
"https://resources.download.minecraft.net/{}/{}",
|
||||||
|
sub_hash, asset.hash
|
||||||
|
))
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let resource_path = assets_path.join(sub_hash).join(&asset.hash);
|
||||||
|
save_file(resource_path.as_path(), &resource);
|
||||||
|
|
||||||
|
if let Some(legacy_path) = legacy_path {
|
||||||
|
let resource_path =
|
||||||
|
legacy_path.join(name.replace('/', &*std::path::MAIN_SEPARATOR.to_string()));
|
||||||
|
save_file(resource_path.as_path(), &resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn download_libraries(libraries_path: &Path, natives_path: &Path, libraries: &[Library]) {
|
||||||
|
future::join_all(
|
||||||
|
libraries
|
||||||
|
.iter()
|
||||||
|
.map(|x| download_library(libraries_path, natives_path, x)),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn download_library(libraries_path: &Path, natives_path: &Path, library: &Library) {
|
||||||
|
if let Some(rules) = &library.rules {
|
||||||
|
let mut allowed = true;
|
||||||
|
|
||||||
|
for rule in rules {
|
||||||
|
match rule.action {
|
||||||
|
RuleAction::Allow => {
|
||||||
|
if let Some(os) = &rule.os {
|
||||||
|
allowed = os.name == &get_os()
|
||||||
|
} else {
|
||||||
|
allowed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RuleAction::Disallow => {
|
||||||
|
if let Some(os) = &rule.os {
|
||||||
|
allowed = os.name != &get_os()
|
||||||
|
} else {
|
||||||
|
allowed = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !allowed {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let name_items = library.name.split(':').collect::<Vec<&str>>();
|
||||||
|
|
||||||
|
let package = name_items.get(0).unwrap();
|
||||||
|
let name = name_items.get(1).unwrap();
|
||||||
|
let version = name_items.get(2).unwrap();
|
||||||
|
|
||||||
|
future::join(
|
||||||
|
download_library_jar(libraries_path, library, package, name, version),
|
||||||
|
download_native(
|
||||||
|
libraries_path,
|
||||||
|
natives_path,
|
||||||
|
library,
|
||||||
|
package,
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn download_library_jar(
|
||||||
|
libraries_path: &Path,
|
||||||
|
library: &Library,
|
||||||
|
package: &str,
|
||||||
|
name: &str,
|
||||||
|
version: &str,
|
||||||
|
) {
|
||||||
|
if let Some(library) = &library.downloads.artifact {
|
||||||
|
let bytes = download_file(&library.url).await;
|
||||||
|
|
||||||
|
save_file(
|
||||||
|
&libraries_path
|
||||||
|
.join(package)
|
||||||
|
.join(name)
|
||||||
|
.join(version)
|
||||||
|
.join(format!("{}-{}.jar", name, version)),
|
||||||
|
&bytes,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn download_native(
|
||||||
|
libraries_path: &Path,
|
||||||
|
natives_path: &Path,
|
||||||
|
library: &Library,
|
||||||
|
package: &str,
|
||||||
|
name: &str,
|
||||||
|
version: &str,
|
||||||
|
) {
|
||||||
|
if let Some(natives) = &library.natives {
|
||||||
|
if let Some(os_key) = natives.get(&get_os()) {
|
||||||
|
if let Some(classifiers) = &library.downloads.classifiers {
|
||||||
|
#[cfg(target_pointer_width = "64")]
|
||||||
|
let parsed_key = os_key.replace("${arch}", "64");
|
||||||
|
#[cfg(target_pointer_width = "32")]
|
||||||
|
let parsed_key = os_key.replace("${arch}", "32");
|
||||||
|
|
||||||
|
if let Some(native) = classifiers.get(&*parsed_key) {
|
||||||
|
let path = &libraries_path
|
||||||
|
.join(package)
|
||||||
|
.join(name)
|
||||||
|
.join(version)
|
||||||
|
.join(format!("{}-{}-{}.jar", name, version, parsed_key));
|
||||||
|
|
||||||
|
let bytes = download_file(&native.url).await;
|
||||||
|
|
||||||
|
save_file(path, &bytes);
|
||||||
|
|
||||||
|
let file = File::open(path).unwrap();
|
||||||
|
let reader = BufReader::new(file);
|
||||||
|
|
||||||
|
let mut archive = zip::ZipArchive::new(reader).unwrap();
|
||||||
|
archive.extract(natives_path).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn save_file(path: &Path, bytes: &bytes::Bytes) {
|
||||||
|
std::fs::create_dir_all(path.parent().unwrap()).unwrap();
|
||||||
|
let mut file = File::create(path).unwrap();
|
||||||
|
file.write_all(bytes).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn download_file(url: &str) -> bytes::Bytes {
|
||||||
|
reqwest::Client::builder()
|
||||||
|
.tcp_keepalive(Some(std::time::Duration::from_secs(10)))
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
.get(url)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.bytes()
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_os() -> Os {
|
||||||
|
match std::env::consts::OS {
|
||||||
|
"windows" => Os::Windows,
|
||||||
|
"macos" => Os::Osx,
|
||||||
|
"linux" => Os::Linux,
|
||||||
|
_ => Os::Unknown,
|
||||||
|
}
|
||||||
|
}
|
||||||
31
theseus/src/launcher/java.rs
Normal file
31
theseus/src/launcher/java.rs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
use lazy_static::lazy_static;
|
||||||
|
use regex::Regex;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
pub enum JavaError {
|
||||||
|
#[error("System Error")]
|
||||||
|
SystemError(#[from] std::io::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref JAVA_VERSION_REGEX: Regex = Regex::new(r#""(.*?)""#).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_java() -> Result<Option<String>, JavaError> {
|
||||||
|
let child = Command::new("/usr/lib/jvm/java-8-openjdk/jre/bin/java")
|
||||||
|
.arg("-version")
|
||||||
|
.output()?;
|
||||||
|
|
||||||
|
let output = &*String::from_utf8_lossy(&*child.stderr);
|
||||||
|
|
||||||
|
if let Some(version_raw) = JAVA_VERSION_REGEX.find(output) {
|
||||||
|
let mut raw = version_raw.as_str().chars();
|
||||||
|
raw.next();
|
||||||
|
raw.next_back();
|
||||||
|
|
||||||
|
return Ok(Some(raw.as_str().to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
161
theseus/src/launcher/meta.rs
Normal file
161
theseus/src/launcher/meta.rs
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
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,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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<Utc>,
|
||||||
|
pub release_time: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct LatestVersion {
|
||||||
|
pub release: String,
|
||||||
|
pub snapshot: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct VersionManifest {
|
||||||
|
pub latest: LatestVersion,
|
||||||
|
pub versions: Vec<Version>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn fetch_version_manifest() -> Result<VersionManifest, reqwest::Error> {
|
||||||
|
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<LibraryDownload>,
|
||||||
|
pub classifiers: Option<HashMap<String, LibraryDownload>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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: Os,
|
||||||
|
pub version: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct LibraryRule {
|
||||||
|
pub action: RuleAction,
|
||||||
|
pub os: Option<OsRule>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct LibraryExtract {
|
||||||
|
pub exclude: Option<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Library {
|
||||||
|
pub downloads: LibraryDownloads,
|
||||||
|
pub extract: Option<LibraryExtract>,
|
||||||
|
pub name: String,
|
||||||
|
pub natives: Option<HashMap<Os, String>>,
|
||||||
|
pub rules: Option<Vec<LibraryRule>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct VersionInfo {
|
||||||
|
pub asset_index: AssetIndex,
|
||||||
|
pub assets: String,
|
||||||
|
pub downloads: HashMap<DownloadType, Download>,
|
||||||
|
pub id: String,
|
||||||
|
pub libraries: Vec<Library>,
|
||||||
|
pub main_class: String,
|
||||||
|
pub minecraft_arguments: String,
|
||||||
|
pub minimum_launcher_version: u32,
|
||||||
|
pub release_time: DateTime<Utc>,
|
||||||
|
pub time: DateTime<Utc>,
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub type_: VersionType,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn fetch_version_info(version: &Version) -> Result<VersionInfo, reqwest::Error> {
|
||||||
|
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<String, Asset>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn fetch_assets_index(version: &VersionInfo) -> Result<AssetsIndex, reqwest::Error> {
|
||||||
|
reqwest::get(&version.asset_index.url).await?.json().await
|
||||||
|
}
|
||||||
4
theseus/src/launcher/mod.rs
Normal file
4
theseus/src/launcher/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
mod auth;
|
||||||
|
pub mod download;
|
||||||
|
pub mod java;
|
||||||
|
pub mod meta;
|
||||||
11
theseus/src/lib.rs
Normal file
11
theseus/src/lib.rs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#![warn(missing_docs, unused_import_braces, missing_debug_implementations)]
|
||||||
|
|
||||||
|
pub mod launcher;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[test]
|
||||||
|
fn it_works() {
|
||||||
|
assert_eq!(2 + 2, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
theseus_cli/Cargo.toml
Normal file
12
theseus_cli/Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "theseus_cli"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Jai A <jaiagr+gpg@pm.me>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
theseus = { path = "../theseus" }
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
futures = "0.3"
|
||||||
28
theseus_cli/src/main.rs
Normal file
28
theseus_cli/src/main.rs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
use futures::{executor, future};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
let mut thing1 = theseus::launcher::meta::fetch_version_manifest()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// future::join_all(thing1.versions.iter().map(|x| async move {
|
||||||
|
// println!("{}", x.url);
|
||||||
|
// let version = theseus::launcher::meta::fetch_version_info(x)
|
||||||
|
// .await
|
||||||
|
// .unwrap();
|
||||||
|
//
|
||||||
|
// println!("{:?}", version);
|
||||||
|
// }))
|
||||||
|
// .await;
|
||||||
|
|
||||||
|
if let Some(version) = thing1.versions.iter().find(|x| &*x.id == "1.17") {
|
||||||
|
println!("{}", version.id);
|
||||||
|
let thing = theseus::launcher::meta::fetch_version_info(&version)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
theseus::launcher::download::download_client(&Path::new("./versions"), &thing).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user