diff options
| author | Filip Wandzio <contact@philw.dev> | 2026-02-25 16:10:23 +0100 |
|---|---|---|
| committer | Filip Wandzio <contact@philw.dev> | 2026-02-25 16:10:23 +0100 |
| commit | f7b4b643ebc52a4d72d90d9adbdddc9aa0721e4a (patch) | |
| tree | c96432be342b02bc0409e5b78b6b5d54afcc7cd6 /src/minecraft/extraction.rs | |
| parent | 2e10b0713f5369f489d2ababd70108cc359c5d2d (diff) | |
| download | dml-f7b4b643ebc52a4d72d90d9adbdddc9aa0721e4a.tar.gz dml-f7b4b643ebc52a4d72d90d9adbdddc9aa0721e4a.zip | |
Feat: Refactor core download logic with concurrency and async features
Implement basic unit testing
Implement automatic java executable switching based on game version
Split loader module into smaller modules
Implement basic documentation
Diffstat (limited to 'src/minecraft/extraction.rs')
| -rw-r--r-- | src/minecraft/extraction.rs | 70 |
1 files changed, 25 insertions, 45 deletions
diff --git a/src/minecraft/extraction.rs b/src/minecraft/extraction.rs index b58fd2e..292566f 100644 --- a/src/minecraft/extraction.rs +++ b/src/minecraft/extraction.rs | |||
| @@ -1,11 +1,17 @@ | |||
| 1 | use std::{fs, io, path::Path}; | 1 | use std::{ |
| 2 | collections::HashMap, | ||
| 3 | fs, | ||
| 4 | fs::File, | ||
| 5 | io, | ||
| 6 | path::{Path, PathBuf}, | ||
| 7 | }; | ||
| 2 | 8 | ||
| 3 | use log::info; | 9 | use zip::{read::ZipFile, ZipArchive}; |
| 4 | use zip::ZipArchive; | ||
| 5 | 10 | ||
| 6 | use crate::{ | 11 | use crate::{ |
| 7 | errors::McError, | 12 | errors::McError, |
| 8 | minecraft::manifests::{Library, Version}, | 13 | minecraft::manifests::{LibraryArtifact, Version}, |
| 14 | util::fs::library_allowed, | ||
| 9 | }; | 15 | }; |
| 10 | 16 | ||
| 11 | pub fn extract_natives( | 17 | pub fn extract_natives( |
| @@ -19,8 +25,6 @@ pub fn extract_natives( | |||
| 19 | .join(&version.id) | 25 | .join(&version.id) |
| 20 | .join("natives"); | 26 | .join("natives"); |
| 21 | 27 | ||
| 22 | info!("Extracting natives for {} into {:?}", version.id, natives_dir); | ||
| 23 | |||
| 24 | if natives_dir.exists() { | 28 | if natives_dir.exists() { |
| 25 | fs::remove_dir_all(&natives_dir)?; | 29 | fs::remove_dir_all(&natives_dir)?; |
| 26 | } | 30 | } |
| @@ -31,75 +35,51 @@ pub fn extract_natives( | |||
| 31 | continue; | 35 | continue; |
| 32 | } | 36 | } |
| 33 | 37 | ||
| 34 | let natives = match &lib.natives { | 38 | let natives: &HashMap<String, String> = match &lib.natives { |
| 35 | | Some(n) => n, | 39 | | Some(n) => n, |
| 36 | | None => continue, | 40 | | None => continue, |
| 37 | }; | 41 | }; |
| 38 | 42 | ||
| 39 | let classifier = match natives.get("linux") { | 43 | let classifier: &String = match natives.get("linux") { |
| 40 | | Some(c) => c, | 44 | | Some(c) => c, |
| 41 | | None => continue, | 45 | | None => continue, |
| 42 | }; | 46 | }; |
| 43 | 47 | ||
| 44 | let classifiers = match &lib.downloads.classifiers { | 48 | let classifiers: &HashMap<String, LibraryArtifact> = |
| 45 | | Some(c) => c, | 49 | match &lib.downloads.classifiers { |
| 46 | | None => continue, | 50 | | Some(c) => c, |
| 47 | }; | 51 | | None => continue, |
| 52 | }; | ||
| 48 | 53 | ||
| 49 | let artifact = match classifiers.get(classifier) { | 54 | let artifact: &LibraryArtifact = match classifiers.get(classifier) { |
| 50 | | Some(a) => a, | 55 | | Some(a) => a, |
| 51 | | None => continue, | 56 | | None => continue, |
| 52 | }; | 57 | }; |
| 53 | 58 | ||
| 54 | let jar_path = cfg | 59 | let jar_path: PathBuf = cfg |
| 55 | .data_dir | 60 | .data_dir |
| 56 | .join("minecraft") | 61 | .join("minecraft") |
| 57 | .join("libraries") | 62 | .join("libraries") |
| 58 | .join(&artifact.path); | 63 | .join(&artifact.path); |
| 59 | 64 | ||
| 60 | info!("Extracting natives from {:?}", jar_path); | ||
| 61 | |||
| 62 | extract_zip(&jar_path, &natives_dir)?; | 65 | extract_zip(&jar_path, &natives_dir)?; |
| 63 | } | 66 | } |
| 64 | 67 | ||
| 65 | Ok(()) | 68 | Ok(()) |
| 66 | } | 69 | } |
| 67 | |||
| 68 | fn library_allowed(lib: &Library) -> bool { | ||
| 69 | let rules = match &lib.rules { | ||
| 70 | | Some(r) => r, | ||
| 71 | | None => return true, | ||
| 72 | }; | ||
| 73 | |||
| 74 | let mut allowed = false; | ||
| 75 | |||
| 76 | for rule in rules { | ||
| 77 | let os_match = match &rule.os { | ||
| 78 | | Some(os) => os.name == "linux", | ||
| 79 | | None => true, | ||
| 80 | }; | ||
| 81 | |||
| 82 | if os_match { | ||
| 83 | allowed = rule.action == "allow"; | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | allowed | ||
| 88 | } | ||
| 89 | |||
| 90 | fn extract_zip(jar_path: &Path, out_dir: &Path) -> Result<(), McError> { | 70 | fn extract_zip(jar_path: &Path, out_dir: &Path) -> Result<(), McError> { |
| 91 | let file = fs::File::open(jar_path)?; | 71 | let file: File = File::open(jar_path)?; |
| 92 | let mut zip = ZipArchive::new(file)?; | 72 | let mut zip: ZipArchive<File> = ZipArchive::new(file)?; |
| 93 | 73 | ||
| 94 | for i in 0..zip.len() { | 74 | for i in 0..zip.len() { |
| 95 | let mut entry = zip.by_index(i)?; | 75 | let mut entry: ZipFile<File> = zip.by_index(i)?; |
| 96 | let name = entry.name(); | 76 | let name: &str = entry.name(); |
| 97 | 77 | ||
| 98 | if name.starts_with("META-INF/") { | 78 | if name.starts_with("META-INF/") { |
| 99 | continue; | 79 | continue; |
| 100 | } | 80 | } |
| 101 | 81 | ||
| 102 | let out_path = out_dir.join(name); | 82 | let out_path: PathBuf = out_dir.join(name); |
| 103 | 83 | ||
| 104 | if entry.is_dir() { | 84 | if entry.is_dir() { |
| 105 | fs::create_dir_all(&out_path)?; | 85 | fs::create_dir_all(&out_path)?; |
| @@ -110,7 +90,7 @@ fn extract_zip(jar_path: &Path, out_dir: &Path) -> Result<(), McError> { | |||
| 110 | fs::create_dir_all(parent)?; | 90 | fs::create_dir_all(parent)?; |
| 111 | } | 91 | } |
| 112 | 92 | ||
| 113 | let mut out_file = fs::File::create(&out_path)?; | 93 | let mut out_file: File = File::create(&out_path)?; |
| 114 | io::copy(&mut entry, &mut out_file)?; | 94 | io::copy(&mut entry, &mut out_file)?; |
| 115 | } | 95 | } |
| 116 | 96 | ||
