use crate::consts;
use crate::minecraft::models::{LibraryDownloads, LibraryExtract, LibraryNatives, Rule};
use crate::utils::Architecture;
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Library {
pub downloads: LibraryDownloads,
pub name: String,
pub natives: Option<LibraryNatives>,
#[serde(default)]
pub rules: Vec<Rule>,
pub extract: Option<LibraryExtract>,
}
impl Library {
pub fn check_use(&self) -> bool {
for rule in &self.rules {
if !rule.allows() {
return false;
}
}
true
}
pub fn jar_name(&self) -> String {
let split = self.split_name();
let parts = split.iter().skip(1).take(2).cloned();
let suffixes = split.iter().skip(3).cloned();
let mut name = vec![];
name.extend(parts);
if let Some(native) = self.get_native() {
name.push(native);
}
name.extend(suffixes);
let mut name = name.join("-");
name.push_str(".jar");
name
}
pub fn library_path(&self, libraries_path: impl AsRef<Path>) -> PathBuf {
let mut library_path = PathBuf::from(libraries_path.as_ref());
library_path.push(self.relative_library_path());
library_path
}
pub fn relative_library_path(&self) -> PathBuf {
let path_parts = self.split_name().into_iter().take(3);
let mut library_path = PathBuf::new();
for (i, path_part) in path_parts.enumerate() {
let part = match i {
0 => path_part.replace('.', "/"),
_ => path_part,
};
library_path.push(part);
}
library_path
}
pub fn jar_path(&self, libraries_path: impl AsRef<Path>) -> PathBuf {
let mut jar_path = self.library_path(&libraries_path);
jar_path.push(self.jar_name());
jar_path
}
pub fn relative_jar_path(&self) -> PathBuf {
let mut jar_path = self.relative_library_path();
jar_path.push(self.jar_name());
jar_path
}
pub fn download_url(&self) -> (String, Option<String>, Option<usize>) {
let url: String;
let mut sha1 = None;
let mut size = None;
match &self.get_native() {
Some(native) => match self.downloads.classifiers.get(native) {
Some(file) => {
url = file.url.clone();
sha1 = Some(file.sha1.clone());
size = Some(file.size);
}
None => {
url = self.build_url_from_name();
}
},
None => match &self.downloads.artifact {
Some(file) => {
url = file.url.clone();
sha1 = Some(file.sha1.clone());
size = Some(file.size);
}
None => {
url = self.build_url_from_name();
}
},
}
(url, sha1, size)
}
pub fn needs_extract(&self) -> bool {
self.get_native().is_some() && self.extract.is_some()
}
fn build_url_from_name(&self) -> String {
let parts = self.split_name().into_iter().take(3);
let mut url = vec![consts::MC_LIBRARIES_BASE_URL.to_string()];
for (i, part) in parts.enumerate() {
if i == 0 {
url.push(part.replace('.', "/"));
} else {
url.push(part);
}
}
url.push(self.jar_name());
url.join("/")
}
pub fn get_native(&self) -> Option<String> {
let arch = Architecture::current();
self.natives.as_ref().and_then(|natives| {
natives
.get_for_current_platform()
.map(|n| n.replace("${arch}", &arch.get_bits().to_string()))
})
}
fn split_name(&self) -> Vec<String> {
self.name.split(':').map(String::from).collect()
}
}