aboutsummaryrefslogtreecommitdiffstats
path: root/src/minecraft/extraction.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/minecraft/extraction.rs116
1 files changed, 112 insertions, 4 deletions
diff --git a/src/minecraft/extraction.rs b/src/minecraft/extraction.rs
index 5175ee0..b58fd2e 100644
--- a/src/minecraft/extraction.rs
+++ b/src/minecraft/extraction.rs
@@ -1,10 +1,118 @@
1use std::{fs, io, path::Path};
2
1use log::info; 3use log::info;
4use zip::ZipArchive;
5
6use crate::{
7 errors::McError,
8 minecraft::manifests::{Library, Version},
9};
2 10
3use crate::errors::McError;
4pub fn extract_natives( 11pub fn extract_natives(
5 _cfg: &crate::config::Config, 12 cfg: &crate::config::Config,
6 version: &crate::minecraft::manifests::Version, 13 version: &Version,
7) -> Result<(), McError> { 14) -> Result<(), McError> {
8 info!("Extracting natives for {}", version.id); 15 let natives_dir = cfg
16 .data_dir
17 .join("minecraft")
18 .join("versions")
19 .join(&version.id)
20 .join("natives");
21
22 info!("Extracting natives for {} into {:?}", version.id, natives_dir);
23
24 if natives_dir.exists() {
25 fs::remove_dir_all(&natives_dir)?;
26 }
27 fs::create_dir_all(&natives_dir)?;
28
29 for lib in &version.libraries {
30 if !library_allowed(lib) {
31 continue;
32 }
33
34 let natives = match &lib.natives {
35 | Some(n) => n,
36 | None => continue,
37 };
38
39 let classifier = match natives.get("linux") {
40 | Some(c) => c,
41 | None => continue,
42 };
43
44 let classifiers = match &lib.downloads.classifiers {
45 | Some(c) => c,
46 | None => continue,
47 };
48
49 let artifact = match classifiers.get(classifier) {
50 | Some(a) => a,
51 | None => continue,
52 };
53
54 let jar_path = cfg
55 .data_dir
56 .join("minecraft")
57 .join("libraries")
58 .join(&artifact.path);
59
60 info!("Extracting natives from {:?}", jar_path);
61
62 extract_zip(&jar_path, &natives_dir)?;
63 }
64
65 Ok(())
66}
67
68fn 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
90fn extract_zip(jar_path: &Path, out_dir: &Path) -> Result<(), McError> {
91 let file = fs::File::open(jar_path)?;
92 let mut zip = ZipArchive::new(file)?;
93
94 for i in 0..zip.len() {
95 let mut entry = zip.by_index(i)?;
96 let name = entry.name();
97
98 if name.starts_with("META-INF/") {
99 continue;
100 }
101
102 let out_path = out_dir.join(name);
103
104 if entry.is_dir() {
105 fs::create_dir_all(&out_path)?;
106 continue;
107 }
108
109 if let Some(parent) = out_path.parent() {
110 fs::create_dir_all(parent)?;
111 }
112
113 let mut out_file = fs::File::create(&out_path)?;
114 io::copy(&mut entry, &mut out_file)?;
115 }
116
9 Ok(()) 117 Ok(())
10} 118}