You've already forked AstralRinth
forked from didirus/AstralRinth
Fix crash when MC updates (#14)
* Fix crash when MC updates * Fix fabric ordering + add neoforge support * run clippy * run clippy
This commit is contained in:
@@ -4,7 +4,7 @@ use crate::minecraft::{
|
|||||||
Argument, ArgumentType, Library, VersionInfo, VersionType,
|
Argument, ArgumentType, Library, VersionInfo, VersionType,
|
||||||
};
|
};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Deserializer, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[cfg(feature = "bincode")]
|
#[cfg(feature = "bincode")]
|
||||||
@@ -32,6 +32,21 @@ pub struct SidedDataEntry {
|
|||||||
pub server: String,
|
pub server: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_date<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let s = String::deserialize(deserializer)?;
|
||||||
|
|
||||||
|
DateTime::parse_from_rfc3339(&s)
|
||||||
|
.map(|dt| dt.with_timezone(&Utc))
|
||||||
|
.or_else(|_| {
|
||||||
|
DateTime::parse_from_str(&s, "%Y-%m-%dT%H:%M:%S%.f")
|
||||||
|
.map(|dt| dt.with_timezone(&Utc))
|
||||||
|
})
|
||||||
|
.map_err(serde::de::Error::custom)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "bincode", derive(Encode, Decode))]
|
#[cfg_attr(feature = "bincode", derive(Encode, Decode))]
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
@@ -43,9 +58,11 @@ pub struct PartialVersionInfo {
|
|||||||
pub inherits_from: String,
|
pub inherits_from: String,
|
||||||
/// The time that the version was released
|
/// The time that the version was released
|
||||||
#[cfg_attr(feature = "bincode", bincode(with_serde))]
|
#[cfg_attr(feature = "bincode", bincode(with_serde))]
|
||||||
|
#[serde(deserialize_with = "deserialize_date")]
|
||||||
pub release_time: DateTime<Utc>,
|
pub release_time: DateTime<Utc>,
|
||||||
/// The latest time a file in this version was updated
|
/// The latest time a file in this version was updated
|
||||||
#[cfg_attr(feature = "bincode", bincode(with_serde))]
|
#[cfg_attr(feature = "bincode", bincode(with_serde))]
|
||||||
|
#[serde(deserialize_with = "deserialize_date")]
|
||||||
pub time: DateTime<Utc>,
|
pub time: DateTime<Utc>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
/// The classpath to the main class to launch the game
|
/// The classpath to the main class to launch the game
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ pub async fn retrieve_data(
|
|||||||
uploaded_files: &mut Vec<String>,
|
uploaded_files: &mut Vec<String>,
|
||||||
semaphore: Arc<Semaphore>,
|
semaphore: Arc<Semaphore>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mut list = fetch_fabric_versions(None, semaphore.clone()).await?;
|
let list = fetch_fabric_versions(None, semaphore.clone()).await?;
|
||||||
let old_manifest = daedalus::modded::fetch_manifest(&format_url(&format!(
|
let old_manifest = daedalus::modded::fetch_manifest(&format_url(&format!(
|
||||||
"fabric/v{}/manifest.json",
|
"fabric/v{}/manifest.json",
|
||||||
daedalus::modded::CURRENT_FABRIC_FORMAT_VERSION,
|
daedalus::modded::CURRENT_FABRIC_FORMAT_VERSION,
|
||||||
@@ -51,9 +51,6 @@ pub async fn retrieve_data(
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list.loader
|
|
||||||
.retain(|x| loaders.iter().any(|val| val.1 == x.version))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const DUMMY_GAME_VERSION: &str = "1.19.4-rc2";
|
const DUMMY_GAME_VERSION: &str = "1.19.4-rc2";
|
||||||
|
|||||||
@@ -141,18 +141,39 @@ pub async fn retrieve_data(
|
|||||||
let mut cloned_manifest =
|
let mut cloned_manifest =
|
||||||
cloned_manifest_mutex.lock().await;
|
cloned_manifest_mutex.lock().await;
|
||||||
|
|
||||||
let position = cloned_manifest
|
if let Some(position) = cloned_manifest
|
||||||
.versions
|
.versions
|
||||||
.iter()
|
.iter()
|
||||||
.position(|x| version.id == x.id)
|
.position(|x| version.id == x.id)
|
||||||
.unwrap();
|
{
|
||||||
cloned_manifest.versions[position].url =
|
cloned_manifest.versions[position].url =
|
||||||
format_url(&version_path);
|
format_url(&version_path);
|
||||||
cloned_manifest.versions[position].assets_index_sha1 =
|
cloned_manifest.versions[position].assets_index_sha1 =
|
||||||
Some(version_info.asset_index.sha1.clone());
|
Some(version_info.asset_index.sha1.clone());
|
||||||
cloned_manifest.versions[position].assets_index_url =
|
cloned_manifest.versions[position].assets_index_url =
|
||||||
Some(format_url(&assets_path));
|
Some(format_url(&assets_path));
|
||||||
cloned_manifest.versions[position].sha1 = version_info_hash;
|
cloned_manifest.versions[position].sha1 =
|
||||||
|
version_info_hash;
|
||||||
|
} else {
|
||||||
|
cloned_manifest.versions.insert(
|
||||||
|
0,
|
||||||
|
daedalus::minecraft::Version {
|
||||||
|
id: version_info.id.clone(),
|
||||||
|
type_: version_info.type_.clone(),
|
||||||
|
url: format_url(&version_path),
|
||||||
|
time: version_info.time,
|
||||||
|
release_time: version_info.release_time,
|
||||||
|
sha1: version_info_hash,
|
||||||
|
compliance_level: 1,
|
||||||
|
assets_index_url: Some(
|
||||||
|
version_info.asset_index.sha1.clone(),
|
||||||
|
),
|
||||||
|
assets_index_sha1: Some(
|
||||||
|
version_info.asset_index.sha1.clone(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut download_assets = false;
|
let mut download_assets = false;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ pub async fn retrieve_data(
|
|||||||
uploaded_files: &mut Vec<String>,
|
uploaded_files: &mut Vec<String>,
|
||||||
semaphore: Arc<Semaphore>,
|
semaphore: Arc<Semaphore>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let maven_metadata = fetch_maven_metadata(None, semaphore.clone()).await?;
|
let maven_metadata = fetch_maven_metadata(semaphore.clone()).await?;
|
||||||
let old_manifest = daedalus::modded::fetch_manifest(&format_url(&format!(
|
let old_manifest = daedalus::modded::fetch_manifest(&format_url(&format!(
|
||||||
"neo/v{}/manifest.json",
|
"neo/v{}/manifest.json",
|
||||||
daedalus::modded::CURRENT_NEOFORGE_FORMAT_VERSION,
|
daedalus::modded::CURRENT_NEOFORGE_FORMAT_VERSION,
|
||||||
@@ -42,10 +42,10 @@ pub async fn retrieve_data(
|
|||||||
for (minecraft_version, loader_versions) in maven_metadata.clone() {
|
for (minecraft_version, loader_versions) in maven_metadata.clone() {
|
||||||
let mut loaders = Vec::new();
|
let mut loaders = Vec::new();
|
||||||
|
|
||||||
for (full, loader_version) in loader_versions {
|
for (full, loader_version, new_forge) in loader_versions {
|
||||||
let version = Version::parse(&loader_version)?;
|
let version = Version::parse(&loader_version)?;
|
||||||
|
|
||||||
loaders.push((full, version))
|
loaders.push((full, version, new_forge.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if !loaders.is_empty() {
|
if !loaders.is_empty() {
|
||||||
@@ -53,7 +53,7 @@ pub async fn retrieve_data(
|
|||||||
let mut loaders_versions = Vec::new();
|
let mut loaders_versions = Vec::new();
|
||||||
|
|
||||||
{
|
{
|
||||||
let loaders_futures = loaders.into_iter().map(|(loader_version_full, _)| async {
|
let loaders_futures = loaders.into_iter().map(|(loader_version_full, _, new_forge)| async {
|
||||||
let versions_mutex = Arc::clone(&old_versions);
|
let versions_mutex = Arc::clone(&old_versions);
|
||||||
let visited_assets = Arc::clone(&visited_assets_mutex);
|
let visited_assets = Arc::clone(&visited_assets_mutex);
|
||||||
let uploaded_files_mutex = Arc::clone(&uploaded_files_mutex);
|
let uploaded_files_mutex = Arc::clone(&uploaded_files_mutex);
|
||||||
@@ -72,13 +72,13 @@ pub async fn retrieve_data(
|
|||||||
}
|
}
|
||||||
|
|
||||||
info!("Forge - Installer Start {}", loader_version_full.clone());
|
info!("Forge - Installer Start {}", loader_version_full.clone());
|
||||||
let bytes = download_file(&format!("https://maven.neoforged.net/net/neoforged/forge/{0}/forge-{0}-installer.jar", loader_version_full), None, semaphore.clone()).await?;
|
let bytes = download_file(&format!("https://maven.neoforged.net/net/neoforged/{1}/{0}/{1}-{0}-installer.jar", loader_version_full, if &*new_forge == "true" { "neoforge" } else { "forge" }), None, semaphore.clone()).await?;
|
||||||
|
|
||||||
let reader = std::io::Cursor::new(bytes);
|
let reader = std::io::Cursor::new(bytes);
|
||||||
|
|
||||||
if let Ok(archive) = zip::ZipArchive::new(reader) {
|
if let Ok(archive) = zip::ZipArchive::new(reader) {
|
||||||
let mut archive_clone = archive.clone();
|
let mut archive_clone = archive.clone();
|
||||||
let mut profile = tokio::task::spawn_blocking(move || {
|
let mut profile = tokio::task::spawn_blocking(move || {
|
||||||
let mut install_profile = archive_clone.by_name("install_profile.json")?;
|
let mut install_profile = archive_clone.by_name("install_profile.json")?;
|
||||||
|
|
||||||
let mut contents = String::new();
|
let mut contents = String::new();
|
||||||
@@ -404,8 +404,10 @@ pub async fn retrieve_data(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_MAVEN_METADATA_URL: &str =
|
const DEFAULT_MAVEN_METADATA_URL_1: &str =
|
||||||
"https://maven.neoforged.net/net/neoforged/forge/maven-metadata.xml";
|
"https://maven.neoforged.net/net/neoforged/forge/maven-metadata.xml";
|
||||||
|
const DEFAULT_MAVEN_METADATA_URL_2: &str =
|
||||||
|
"https://maven.neoforged.net/net/neoforged/neoforge/maven-metadata.xml";
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct Metadata {
|
struct Metadata {
|
||||||
@@ -423,32 +425,55 @@ struct Versions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn fetch_maven_metadata(
|
pub async fn fetch_maven_metadata(
|
||||||
url: Option<&str>,
|
|
||||||
semaphore: Arc<Semaphore>,
|
semaphore: Arc<Semaphore>,
|
||||||
) -> Result<HashMap<String, Vec<(String, String)>>, Error> {
|
) -> Result<HashMap<String, Vec<(String, String, bool)>>, Error> {
|
||||||
let values = serde_xml_rs::from_str::<Metadata>(
|
async fn fetch_values(
|
||||||
&String::from_utf8(
|
url: &str,
|
||||||
download_file(
|
semaphore: Arc<Semaphore>,
|
||||||
url.unwrap_or(DEFAULT_MAVEN_METADATA_URL),
|
) -> Result<Metadata, Error> {
|
||||||
None,
|
Ok(serde_xml_rs::from_str(
|
||||||
semaphore,
|
&String::from_utf8(
|
||||||
|
download_file(url, None, semaphore).await?.to_vec(),
|
||||||
)
|
)
|
||||||
.await?
|
.unwrap_or_default(),
|
||||||
.to_vec(),
|
)?)
|
||||||
)
|
}
|
||||||
.unwrap_or_default(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let mut map: HashMap<String, Vec<(String, String)>> = HashMap::new();
|
let forge_values =
|
||||||
|
fetch_values(DEFAULT_MAVEN_METADATA_URL_1, semaphore.clone()).await?;
|
||||||
|
let neo_values =
|
||||||
|
fetch_values(DEFAULT_MAVEN_METADATA_URL_2, semaphore).await?;
|
||||||
|
|
||||||
for value in values.versioning.versions.version {
|
let mut map: HashMap<String, Vec<(String, String, bool)>> = HashMap::new();
|
||||||
|
|
||||||
|
for value in forge_values.versioning.versions.version {
|
||||||
let original = value.clone();
|
let original = value.clone();
|
||||||
|
|
||||||
let parts: Vec<&str> = value.split('-').collect();
|
let parts: Vec<&str> = value.split('-').collect();
|
||||||
if parts.len() == 2 {
|
if parts.len() == 2 {
|
||||||
map.entry(parts[0].to_string())
|
map.entry(parts[0].to_string()).or_default().push((
|
||||||
.or_default()
|
original,
|
||||||
.push((original, parts[1].to_string()));
|
parts[1].to_string(),
|
||||||
|
false,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for value in neo_values.versioning.versions.version {
|
||||||
|
let original = value.clone();
|
||||||
|
|
||||||
|
let mut parts = value.split('.');
|
||||||
|
|
||||||
|
if let Some(major) = parts.next() {
|
||||||
|
if let Some(minor) = parts.next() {
|
||||||
|
let game_version = format!("1.{}.{}", major, minor);
|
||||||
|
|
||||||
|
map.entry(game_version.clone()).or_default().push((
|
||||||
|
original.clone(),
|
||||||
|
format!("{}-{}", game_version, original),
|
||||||
|
true,
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ pub async fn retrieve_data(
|
|||||||
uploaded_files: &mut Vec<String>,
|
uploaded_files: &mut Vec<String>,
|
||||||
semaphore: Arc<Semaphore>,
|
semaphore: Arc<Semaphore>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mut list = fetch_quilt_versions(None, semaphore.clone()).await?;
|
let list = fetch_quilt_versions(None, semaphore.clone()).await?;
|
||||||
let old_manifest = daedalus::modded::fetch_manifest(&format_url(&format!(
|
let old_manifest = daedalus::modded::fetch_manifest(&format_url(&format!(
|
||||||
"quilt/v{}/manifest.json",
|
"quilt/v{}/manifest.json",
|
||||||
daedalus::modded::CURRENT_QUILT_FORMAT_VERSION,
|
daedalus::modded::CURRENT_QUILT_FORMAT_VERSION,
|
||||||
@@ -51,9 +51,6 @@ pub async fn retrieve_data(
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list.loader
|
|
||||||
.retain(|x| loaders.iter().any(|val| val.1 == x.version))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const DUMMY_GAME_VERSION: &str = "1.19.4-rc2";
|
const DUMMY_GAME_VERSION: &str = "1.19.4-rc2";
|
||||||
|
|||||||
Reference in New Issue
Block a user