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
91
92
use crate::error::CobbleResult;
use crate::instance::Instance;
use crate::minecraft::installation_update::InstallationUpdate;
use crossbeam_channel::{Receiver, Sender};
use std::fs;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;

/// Asset Index
mod asset_index;
/// Assets or Resources
mod assets;
/// Installed status
mod check;
/// Client
mod client;
/// Libraries
mod libraries;
/// Log Config
mod log_config;
/// Version Data
mod version_data;

impl Instance {
    /// Provides the channel needed for [`full_install()`](Instance::full_install).
    /// Eliminates the need to use [`crossbeam_channel`](crossbeam_channel) to get the needed channel.
    pub fn update_channel() -> (Sender<InstallationUpdate>, Receiver<InstallationUpdate>) {
        crossbeam_channel::unbounded()
    }

    /// Does a full installation of Minecraft.
    ///
    /// Includes:
    ///
    /// - Version Data
    /// - Asset Index
    /// - Libraries
    /// - Assets or Resources
    /// - Log Config
    /// - Client
    ///
    /// ```rust
    /// # use cobble_core::instance::Instance;
    /// # use cobble_core::error::CobbleResult;
    /// # use std::sync::atomic::AtomicBool;
    /// # use std::sync::Arc;
    /// # use std::thread;
    /// # fn function(instance: Instance) -> CobbleResult<()> {
    /// let (sender, receiver) = Instance::update_channel();
    /// let cancel = Arc::new(AtomicBool::new(false));
    ///
    /// thread::spawn(move || {
    ///     instance.full_install(sender, cancel)
    /// });
    ///
    /// while let Ok(update) = receiver.recv() {
    ///     println!("{:#?}", update);
    /// }
    ///
    /// # Ok(())
    /// # }
    /// ```
    pub fn full_install(
        &self,
        update_sender: Sender<InstallationUpdate>,
        cancel: Arc<AtomicBool>,
    ) -> CobbleResult<()> {
        // Preparation
        fs::create_dir_all(self.instance_path())?;
        self.save_version_data()?;
        self.save_asset_index()?;

        // Resources
        if self.install_libraries(update_sender.clone(), cancel.clone())? {
            return Ok(());
        };
        if self.install_assets(update_sender.clone(), cancel.clone())? {
            return Ok(());
        };
        if self.install_log_config(update_sender.clone(), cancel.clone())? {
            return Ok(());
        };
        if self.install_client(update_sender.clone(), cancel)? {
            return Ok(());
        };

        // Done
        let _ = update_sender.send(InstallationUpdate::Success);

        Ok(())
    }
}