Skip to content

Commit f918542

Browse files
committed
feat: download vanilla when downloading a loader
1 parent 7dc8143 commit f918542

File tree

9 files changed

+186
-39
lines changed

9 files changed

+186
-39
lines changed

crates/client/src/download.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use nomi_core::{
1212
game_paths::GamePaths,
1313
instance::{launch::LaunchSettings, Profile},
1414
loaders::{
15+
combined::VanillaCombinedDownloader,
1516
fabric::Fabric,
1617
forge::{Forge, ForgeVersion},
1718
vanilla::Vanilla,
@@ -49,14 +50,21 @@ async fn try_download_version(profile: Arc<RwLock<ModdedProfile>>, progress_shar
4950
.version(version_profile.version().to_string())
5051
.game_paths(game_paths.clone());
5152

53+
let combined_downloader = VanillaCombinedDownloader::new(version_profile.version(), game_paths.clone()).await?;
5254
let instance = match loader {
53-
Loader::Vanilla => builder.downloader(Box::new(Vanilla::new(version_profile.version(), game_paths.clone()).await?)),
54-
Loader::Fabric { version } => builder.downloader(Box::new(
55-
Fabric::new(version_profile.version(), version.as_ref(), game_paths.clone()).await?,
56-
)),
57-
Loader::Forge => builder.downloader(Box::new(
58-
Forge::new(version_profile.version(), ForgeVersion::Recommended, game_paths.clone()).await?,
59-
)),
55+
Loader::Vanilla => builder.downloader(Box::new(combined_downloader)),
56+
Loader::Fabric { version } => {
57+
let combined = combined_downloader
58+
.with_loader(|game_version, game_paths| Fabric::new(game_version, version.as_ref(), game_paths))
59+
.await?;
60+
builder.downloader(Box::new(combined))
61+
}
62+
Loader::Forge => {
63+
let combined = combined_downloader
64+
.with_loader(|game_version, game_paths| Forge::new(game_version, ForgeVersion::Recommended, game_paths))
65+
.await?;
66+
builder.downloader(Box::new(combined))
67+
}
6068
}
6169
.build();
6270

@@ -70,7 +78,7 @@ async fn try_download_version(profile: Arc<RwLock<ModdedProfile>>, progress_shar
7078

7179
let instance = instance.downloader();
7280
let io = instance.io();
73-
let downloader: Box<dyn Downloader<Data = DownloadResult>> = instance.into_downloader();
81+
let downloader = instance.into_downloader();
7482
io.await?;
7583

7684
let downloader = DownloadQueue::new().with_downloader_dyn(downloader);
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,33 @@
1+
use crate::loaders::{combined::VanillaCombinedDownloader, vanilla::Vanilla, ToLoaderProfile};
2+
13
use super::launch::{LaunchInstanceBuilder, LaunchSettings};
24

35
pub trait LaunchInstanceBuilderExt {
46
fn insert(&self, builder: LaunchInstanceBuilder<LaunchSettings>) -> LaunchInstanceBuilder<LaunchSettings>;
57
}
68

79
const _: Option<Box<dyn LaunchInstanceBuilderExt>> = None;
10+
11+
// Unique case where we do not have a profile.
12+
// TODO: Maybe make a profile for Vanilla and get rid of manifest?
13+
impl LaunchInstanceBuilderExt for Vanilla {
14+
fn insert(&self, builder: LaunchInstanceBuilder<LaunchSettings>) -> LaunchInstanceBuilder<LaunchSettings> {
15+
builder
16+
}
17+
}
18+
19+
// If the generic is `()` that means we are downloading `Vanilla`
20+
impl LaunchInstanceBuilderExt for VanillaCombinedDownloader<()> {
21+
fn insert(&self, builder: LaunchInstanceBuilder<LaunchSettings>) -> LaunchInstanceBuilder<LaunchSettings> {
22+
builder
23+
}
24+
}
25+
26+
impl<L> LaunchInstanceBuilderExt for L
27+
where
28+
L: ToLoaderProfile,
29+
{
30+
fn insert(&self, builder: LaunchInstanceBuilder<LaunchSettings>) -> LaunchInstanceBuilder<LaunchSettings> {
31+
builder.profile(self.to_profile())
32+
}
33+
}

crates/nomi-core/src/instance/marker.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
use std::fmt::Debug;
22

3-
use crate::downloads::traits::{DownloadResult, Downloader};
3+
use crate::{
4+
downloads::traits::{DownloadResult, Downloader},
5+
loaders::vanilla::Vanilla,
6+
};
47

5-
use super::builder_ext::LaunchInstanceBuilderExt;
8+
use super::{
9+
builder_ext::LaunchInstanceBuilderExt,
10+
launch::{LaunchInstanceBuilder, LaunchSettings},
11+
};
612

713
pub trait ProfileDownloader: LaunchInstanceBuilderExt + Downloader<Data = DownloadResult> + Debug + Send + Sync {
814
fn into_downloader(self: Box<Self>) -> Box<dyn Downloader<Data = DownloadResult>>;
+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
use std::{fmt::Debug, future::Future};
2+
3+
use crate::{
4+
downloads::{
5+
progress::ProgressSender,
6+
traits::{DownloadResult, Downloader},
7+
DownloadQueue,
8+
},
9+
game_paths::GamePaths,
10+
instance::marker::ProfileDownloader,
11+
PinnedFutureWithBounds,
12+
};
13+
14+
use super::{vanilla::Vanilla, ToLoaderProfile};
15+
16+
pub struct VanillaCombinedDownloader<T> {
17+
version: String,
18+
game_paths: GamePaths,
19+
vanilla: Vanilla,
20+
loader: T,
21+
}
22+
23+
impl<T> Debug for VanillaCombinedDownloader<T> {
24+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25+
f.debug_struct("VanillaCombinedDownloader")
26+
.field("version", &self.version)
27+
.field("game_paths", &self.game_paths)
28+
.field("vanilla", &self.vanilla)
29+
.field("loader", &"(loader)")
30+
.finish()
31+
}
32+
}
33+
34+
impl VanillaCombinedDownloader<()> {
35+
pub async fn new(game_version: impl Into<String>, game_paths: GamePaths) -> anyhow::Result<Self> {
36+
let version = game_version.into();
37+
let vanilla = Vanilla::new(&version, game_paths.clone()).await?;
38+
39+
Ok(Self {
40+
version,
41+
game_paths,
42+
vanilla,
43+
loader: (),
44+
})
45+
}
46+
47+
pub async fn with_loader<T, F, Fut>(self, fun: F) -> anyhow::Result<VanillaCombinedDownloader<T>>
48+
where
49+
F: FnOnce(String, GamePaths) -> Fut,
50+
Fut: Future<Output = anyhow::Result<T>>,
51+
T: ProfileDownloader,
52+
{
53+
let loader = (fun)(self.version.clone(), self.game_paths.clone()).await?;
54+
55+
Ok(VanillaCombinedDownloader {
56+
version: self.version,
57+
game_paths: self.game_paths,
58+
vanilla: self.vanilla,
59+
loader,
60+
})
61+
}
62+
}
63+
64+
impl<T: ToLoaderProfile> ToLoaderProfile for VanillaCombinedDownloader<T> {
65+
fn to_profile(&self) -> crate::instance::loader::LoaderProfile {
66+
self.loader.to_profile()
67+
}
68+
}
69+
70+
#[async_trait::async_trait]
71+
impl<T: ProfileDownloader + 'static> Downloader for VanillaCombinedDownloader<T> {
72+
type Data = DownloadResult;
73+
74+
fn total(&self) -> u32 {
75+
self.vanilla.total() + self.loader.total()
76+
}
77+
78+
async fn download(self: Box<Self>, sender: &dyn ProgressSender<Self::Data>) {
79+
let downloader = DownloadQueue::new().with_downloader(self.vanilla).with_downloader(self.loader);
80+
let downloader = Box::new(downloader);
81+
downloader.download(sender).await;
82+
}
83+
84+
fn io(&self) -> PinnedFutureWithBounds<anyhow::Result<()>> {
85+
let vanilla_io = self.vanilla.io();
86+
let loader_io = self.loader.io();
87+
88+
Box::pin(async move {
89+
vanilla_io.await?;
90+
loader_io.await
91+
})
92+
}
93+
}
94+
95+
#[async_trait::async_trait]
96+
impl Downloader for VanillaCombinedDownloader<()> {
97+
type Data = DownloadResult;
98+
99+
fn total(&self) -> u32 {
100+
self.vanilla.total()
101+
}
102+
103+
async fn download(self: Box<Self>, sender: &dyn ProgressSender<Self::Data>) {
104+
Box::new(self.vanilla).download(sender).await;
105+
}
106+
107+
fn io(&self) -> PinnedFutureWithBounds<anyhow::Result<()>> {
108+
self.vanilla.io()
109+
}
110+
}

crates/nomi-core/src/loaders/fabric.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ use crate::{
3131
PinnedFutureWithBounds,
3232
};
3333

34+
use super::ToLoaderProfile;
35+
3436
#[derive(Debug)]
3537
pub struct Fabric {
3638
pub game_version: String,
@@ -91,8 +93,10 @@ impl Fabric {
9193
libraries_downloader,
9294
})
9395
}
96+
}
9497

95-
pub fn to_profile(&self) -> LoaderProfile {
98+
impl ToLoaderProfile for Fabric {
99+
fn to_profile(&self) -> LoaderProfile {
96100
LoaderProfile {
97101
loader: Loader::Fabric {
98102
version: Some(self.fabric_version.clone()),
@@ -151,9 +155,3 @@ impl Downloader for Fabric {
151155
Box::pin(fut)
152156
}
153157
}
154-
155-
impl LaunchInstanceBuilderExt for Fabric {
156-
fn insert(&self, builder: LaunchInstanceBuilder<LaunchSettings>) -> LaunchInstanceBuilder<LaunchSettings> {
157-
builder.profile(self.to_profile())
158-
}
159-
}

crates/nomi-core/src/loaders/forge.rs

+13-15
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ use crate::{
3838
PinnedFutureWithBounds, DOT_NOMI_TEMP_DIR,
3939
};
4040

41+
use super::ToLoaderProfile;
42+
4143
const FORGE_REPO_URL: &str = "https://maven.minecraftforge.net";
4244

4345
const _NEO_FORGE_REPO_URL: &str = "https://maven.neoforged.net/releases/";
@@ -69,15 +71,6 @@ pub struct Forge {
6971
}
7072

7173
impl Forge {
72-
pub fn to_profile(&self) -> LoaderProfile {
73-
LoaderProfile {
74-
loader: Loader::Forge,
75-
main_class: self.profile.main_class().to_string(),
76-
args: self.profile.simple_args(),
77-
libraries: self.profile.simple_libraries(),
78-
}
79-
}
80-
8174
#[tracing::instrument(skip_all, err)]
8275
pub async fn get_versions(game_version: impl Into<String>) -> anyhow::Result<Vec<String>> {
8376
let game_version = game_version.into();
@@ -291,6 +284,17 @@ impl Forge {
291284
}
292285
}
293286

287+
impl ToLoaderProfile for Forge {
288+
fn to_profile(&self) -> LoaderProfile {
289+
LoaderProfile {
290+
loader: Loader::Forge,
291+
main_class: self.profile.main_class().to_string(),
292+
args: self.profile.simple_args(),
293+
libraries: self.profile.simple_libraries(),
294+
}
295+
}
296+
}
297+
294298
fn forge_installer_path(game_version: &str, forge_version: &str) -> PathBuf {
295299
Path::new(DOT_NOMI_TEMP_DIR).join(format!("{game_version}-{forge_version}.jar"))
296300
}
@@ -389,12 +393,6 @@ impl Downloader for Forge {
389393
}
390394
}
391395

392-
impl LaunchInstanceBuilderExt for Forge {
393-
fn insert(&self, builder: LaunchInstanceBuilder<LaunchSettings>) -> LaunchInstanceBuilder<LaunchSettings> {
394-
builder.profile(self.to_profile())
395-
}
396-
}
397-
398396
#[derive(Debug, Clone)]
399397
struct ProcessorsData {
400398
processors: Vec<Processor>,

crates/nomi-core/src/loaders/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
use crate::instance::loader::LoaderProfile;
2+
3+
pub mod combined;
14
pub mod fabric;
25
pub mod forge;
36
pub mod vanilla;
7+
8+
pub trait ToLoaderProfile {
9+
fn to_profile(&self) -> LoaderProfile;
10+
}

crates/nomi-core/src/loaders/vanilla.rs

-6
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,3 @@ impl Downloader for Vanilla {
141141
Box::pin(fut)
142142
}
143143
}
144-
145-
impl LaunchInstanceBuilderExt for Vanilla {
146-
fn insert(&self, builder: LaunchInstanceBuilder<LaunchSettings>) -> LaunchInstanceBuilder<LaunchSettings> {
147-
builder
148-
}
149-
}

crates/nomi-core/tests/vanilla_test.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use nomi_core::{instance::launch::LaunchSettings, repository::java_runner::JavaRunner};
1+
use nomi_core::instance::launch::LaunchSettings;
22

33
#[tokio::test]
44
async fn vanilla_test() {

0 commit comments

Comments
 (0)