Skip to content

Commit

Permalink
GAAAAAAA WAAAAAAAAA
Browse files Browse the repository at this point in the history
  • Loading branch information
RedstoneWizard08 committed Aug 29, 2024
1 parent ead7267 commit 6b575f6
Show file tree
Hide file tree
Showing 28 changed files with 674 additions and 103 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 0 additions & 12 deletions crates/api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
use whcore::type_map;

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate serde;

#[macro_use]
extern crate specta;

#[macro_use]
extern crate async_trait;

type_map! {}
3 changes: 0 additions & 3 deletions crates/commands/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
use whcore::type_map;

#[macro_use]
extern crate tracing;

type_map! {}
4 changes: 4 additions & 0 deletions crates/core/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,8 @@ impl CoreManager {
pub fn create_dir(&self, dir: impl Into<PathBuf>) {
fs::create_dir_all(dir.into()).unwrap();
}

pub fn dir(&self, dir: impl AsRef<str>) -> PathBuf {
self.root.join(dir.as_ref())
}
}
1 change: 1 addition & 0 deletions crates/mcmeta/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ futures.workspace = true
specta.workspace = true
data.workspace = true
tracing.workspace = true
bytes.workspace = true
28 changes: 26 additions & 2 deletions crates/mcmeta/src/fabric/mod.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
//! The module for Fabric
use std::cell::LazyCell;

use anyhow::Result;
use meta::FabricMetaVersion;
use whcore::async_trait::async_trait;

use crate::{
installer::manifest::InstallerManifest,
loader::LoaderData,
maven::{artifact::Artifact, MavenRepo},
vanilla::manifest::VersionManifest,
};

pub mod meta;

pub const MAVEN_REPO: MavenRepo = MavenRepo::new("https://maven.fabricmc.net");
pub const MAVEN_REPO: LazyCell<MavenRepo> =
LazyCell::new(|| MavenRepo::new("https://maven.fabricmc.net".into()));
pub const META_API: &str = "https://meta.fabricmc.net/v2/versions/loader";

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Type)]
Expand All @@ -26,7 +31,7 @@ impl LoaderData for Fabric {
.await?
.iter()
.map(|v| v.maven.clone().into())
.collect())
.collect::<Vec<_>>())
}

async fn versions_for(&self, _game_version: impl AsRef<str> + Send) -> Result<Vec<Artifact>> {
Expand All @@ -36,4 +41,23 @@ impl LoaderData for Fabric {
async fn version_jar_url(&self, artifact: impl Into<Artifact> + Send) -> Result<String> {
Ok(MAVEN_REPO.get_artifact_url(artifact))
}

async fn get_version_manifest(
&self,
version: impl Into<Artifact> + Send,
game_version: impl AsRef<str> + Send,
) -> Result<VersionManifest> {
let url = format!(
"https://meta.fabricmc.net/v2/versions/loader/{}/{}/profile/json",
game_version.as_ref(),
version.into().version.unwrap()
);

let data = reqwest::get(url).await?.text().await?;
let data = serde_json::from_str::<InstallerManifest>(&data)?;

Ok(data
.resolve(game_version.as_ref().to_string(), MAVEN_REPO.clone())
.await?)
}
}
24 changes: 23 additions & 1 deletion crates/mcmeta/src/forge/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,21 @@
//!
//! Versions must be queried from Forge's maven, with the artifact `net.minecraftforge:forge`
use std::cell::LazyCell;

use anyhow::Result;
use whcore::async_trait::async_trait;

use crate::{
installer::manifest::InstallerManifest,
loader::LoaderData,
maven::{artifact::Artifact, MavenRepo},
util::get_file_from_zip,
vanilla::manifest::VersionManifest,
};

pub const MAVEN_REPO: MavenRepo = MavenRepo::new("https://maven.minecraftforge.net");
pub const MAVEN_REPO: LazyCell<MavenRepo> =
LazyCell::new(|| MavenRepo::new("https://maven.minecraftforge.net".into()));

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Type)]
pub struct Forge;
Expand All @@ -39,4 +45,20 @@ impl LoaderData for Forge {
async fn version_jar_url(&self, artifact: impl Into<Artifact> + Send) -> Result<String> {
Ok(MAVEN_REPO.get_artifact_url(artifact))
}

async fn get_version_manifest(
&self,
version: impl Into<Artifact> + Send,
game_version: impl AsRef<str> + Send,
) -> Result<VersionManifest> {
let artifact = version.into().set_classifier("installer");
let url = self.version_jar_url(artifact).await?;
let data = reqwest::get(url).await?.bytes().await?;
let data = get_file_from_zip(data, "version.json")?;
let manifest = serde_json::from_str::<InstallerManifest>(&data)?;

Ok(manifest
.resolve(game_version.as_ref().to_string(), MAVEN_REPO.clone())
.await?)
}
}
71 changes: 71 additions & 0 deletions crates/mcmeta/src/installer/libs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use std::{collections::HashMap, fs, path::PathBuf};
use anyhow::Result;
use tokio_stream::StreamExt;
use crate::vanilla::manifest::libraries::Library;

pub struct LibraryInstaller {
/// A list of listeners.
/// Fn(output_path, downloaded, total_bytes)
listeners: Vec<Box<dyn Fn(&PathBuf, u64, u64)>>,
}

impl LibraryInstaller {
pub fn new() -> Self {
Self {
listeners: Vec::new(),
}
}

pub fn add_listener<T>(&mut self, func: T) -> &mut Self where T: Fn(&PathBuf, u64, u64) + 'static {
self.listeners.push(Box::new(func));
self
}

/// Download library files into a root directory.
///
/// Args:
/// - root: The root of the library folder.
/// - libs: The libraries to download.
/// - features: Enabled launcher features.
pub async fn install_libraries(&self, root: PathBuf, libs: Vec<Library>, features: &HashMap<String, bool>) -> Result<()> {
for lib in libs {
let files = lib.get_files(features);

for file in files {
let path = root.join(file.path());

if path.exists() {
self.notify_progress(&path, 1, 1);
continue;
}

let mut tmp_path = path.clone();
let parent = path.parent().unwrap();

tmp_path.add_extension(".tmp");
fs::create_dir_all(parent)?;

let req = reqwest::get(file.url).await?;
let total = req.content_length().unwrap_or_default();
let mut stream = req.bytes_stream();
let mut data = Vec::new();

while let Some(Ok(chunk)) = stream.next().await {
data.extend(chunk);
self.notify_progress(&path, data.len() as u64, total);
}

fs::write(&tmp_path, data)?;
fs::rename(tmp_path, path)?;
}
}

Ok(())
}

fn notify_progress(&self, path: &PathBuf, downloaded: u64, total: u64) {
for listener in &self.listeners {
listener(path, downloaded, total);
}
}
}
99 changes: 99 additions & 0 deletions crates/mcmeta/src/installer/manifest.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
use std::collections::HashMap;

use anyhow::Result;

use crate::{
maven::{artifact::Artifact, MavenRepo},
vanilla::{
manifest::{
args::Arguments,
libraries::{Library, LibraryDownloads, LibraryFile},
VersionManifest,
},
meta::PistonMetaVersionType,
Vanilla,
},
};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InstallerManifest {
pub id: String,
pub time: String,
pub release_time: Option<String>,
#[serde(rename = "type")]
pub kind: PistonMetaVersionType,
pub main_class: Option<String>,
pub inherits_from: Option<String>,
pub arguments: Arguments,
pub libraries: Vec<InstallerLibraryFile>,
}

#[derive(Debug, Clone, Serialize, Deserialize, Type, Default)]
pub struct InstallerLibraryFile {
pub name: String,
pub sha1: Option<String>,
pub size: Option<u64>,
pub url: Option<String>,
}

impl InstallerLibraryFile {
pub fn into_lib(self, maven: MavenRepo) -> LibraryFile {
let mvn_url = self
.url
.clone()
.map(MavenRepo::new)
.unwrap_or(maven)
.get_artifact_url(self.name.clone());

let url = if let Some(url) = self.url {
if url.starts_with("http") {
url
} else {
mvn_url
}
} else {
mvn_url
};

LibraryFile {
path: Artifact::new(self.name).url(),
url,
size: self.size,
sha1: self.sha1,
}
}
}

impl InstallerManifest {
pub fn merge(&self, mut full: VersionManifest, maven: MavenRepo) -> VersionManifest {
if let Some(main) = self.main_class.clone() {
full.main_class = main;
}

if let Some(args) = &mut full.arguments {
args.extend(self.arguments.clone());
}

for lib in &self.libraries {
full.libraries.push(Library {
name: lib.name.clone(),
rules: Vec::new(),

downloads: LibraryDownloads {
artifact: Some(lib.clone().into_lib(maven.clone())),
classifiers: HashMap::new(),
},
});
}

full
}

pub async fn resolve(
&self,
inherits_from: String,
maven: MavenRepo,
) -> Result<VersionManifest> {
Ok(self.merge(Vanilla.get_manifest_for(inherits_from).await?, maven))
}
}
2 changes: 2 additions & 0 deletions crates/mcmeta/src/installer/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod manifest;
pub mod libs;
7 changes: 7 additions & 0 deletions crates/mcmeta/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![feature(path_add_extension)]

use fabric::{meta::FabricMetaVersion, Fabric};
use forge::Forge;
use maven::{
Expand All @@ -24,12 +26,17 @@ pub extern crate anyhow;

pub mod fabric;
pub mod forge;
pub mod installer;
pub mod loader;
pub mod maven;
pub mod neoforge;
pub mod quilt;
pub mod util;
pub mod vanilla;

#[cfg(test)]
pub mod tests;

type_map! {
MavenRepo,
Artifact,
Expand Down
8 changes: 7 additions & 1 deletion crates/mcmeta/src/loader/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
use anyhow::Result;
use whcore::async_trait::async_trait;

use crate::maven::artifact::Artifact;
use crate::{maven::artifact::Artifact, vanilla::manifest::VersionManifest};

#[async_trait]
pub trait LoaderData {
async fn all_versions(&self) -> Result<Vec<Artifact>>;
async fn versions_for(&self, game_version: impl AsRef<str> + Send) -> Result<Vec<Artifact>>;
async fn version_jar_url(&self, version: impl Into<Artifact> + Send) -> Result<String>;

async fn get_version_manifest(
&self,
version: impl Into<Artifact> + Send,
game_version: impl AsRef<str> + Send,
) -> Result<VersionManifest>;
}
Loading

0 comments on commit 6b575f6

Please sign in to comment.