1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use crate::error::{CobbleError, CobbleResult};
use crate::minecraft::models::{VersionData, VersionManifest};
use crate::minecraft::{
    install_assets, install_client, install_fabric_libraries, install_libraries,
    install_log_config, FabricVersionData, InstallOptionsBuilder, InstallationUpdate,
};
use crate::Instance;
use tokio::sync::mpsc::Sender;

impl Instance {
    /// Performs a full installation of Minecraft.
    ///
    /// Includes
    ///
    /// - Saving version data
    /// - Saving fabric version data
    /// - Libraries
    /// - Fabric libraries (when enabled)
    /// - Assets / Resources
    /// - Log config
    /// - Client
    #[instrument(
        name = "full_installation",
        level = "debug",
        skip_all,
        fields(
            version = &self.version,
            parallel,
            retries,
            verify,
        )
    )]
    pub async fn full_installation(
        &mut self,
        parallel: u16,
        retries: u16,
        verify: bool,
        update_sender: Sender<InstallationUpdate>,
    ) -> CobbleResult<()> {
        trace!("Fetching version manifest");
        let manifest = VersionManifest::fetch().await?;

        trace!("Fetching version data");
        let summary = manifest
            .versions
            .get(&self.version)
            .ok_or_else(|| CobbleError::InvalidVersion(self.version.clone()))?;
        let version_data = VersionData::fetch(&summary.url).await?;

        trace!("Saving version data");
        self.save_version_data(&version_data).await?;

        trace!("Fetching asset index");
        let asset_index = version_data.asset_index.fetch_index().await?;

        let options = InstallOptionsBuilder::default()
            .version_data(version_data)
            .asset_index(asset_index)
            .libraries_path(self.libraries_path())
            .natives_path(self.natives_path())
            .assets_path(self.assets_path())
            .log_configs_path(self.log_configs_path())
            .minecraft_path(self.dot_minecraft_path())
            .parallel_downloads(parallel)
            .download_retries(retries)
            .verify_downloads(verify)
            .build()
            .unwrap();

        install_libraries(&options, update_sender.clone()).await?;
        install_assets(&options, update_sender.clone()).await?;
        install_log_config(&options, update_sender.clone()).await?;
        install_client(&options, update_sender.clone()).await?;

        // Fabric
        if let Some(fabric_version) = &self.fabric_version {
            trace!("Fetching fabric version data");
            let fabric_version_data =
                FabricVersionData::fetch(&self.version, fabric_version).await?;

            trace!("Saving fabric version data");
            self.save_fabric_version_data(&fabric_version_data).await?;

            install_fabric_libraries(&fabric_version_data, &options, update_sender).await?;
        }

        self.installed = true;
        Ok(())
    }
}