Skip to main content

lighty_launch/instance/
utilities.rs

1use lighty_loaders::types::{InstanceSize, VersionInfo};
2use lighty_loaders::types::version_metadata::Version;
3
4use super::errors::{InstanceError, InstanceResult};
5use super::INSTANCE_MANAGER;
6
7/// Extension trait providing instance management utilities.
8///
9/// Auto-implemented for every [`VersionInfo`].
10#[allow(async_fn_in_trait)]
11pub trait InstanceControl: VersionInfo {
12    /// Returns the first PID of a running instance, or `None` if not running.
13    fn get_pid(&self) -> Option<u32> {
14        INSTANCE_MANAGER.get_pid(self.name())
15    }
16
17    /// Returns all PIDs running under this instance name.
18    fn get_pids(&self) -> Vec<u32> {
19        INSTANCE_MANAGER.get_pids(self.name())
20    }
21
22    /// Closes a specific instance by PID.
23    async fn close_instance(&self, pid: u32) -> InstanceResult<()> {
24        INSTANCE_MANAGER.close_instance(pid).await
25    }
26
27    /// Deletes the instance from disk. Errors if any process is still running.
28    async fn delete_instance(&self) -> InstanceResult<()> {
29        let running_pids = self.get_pids();
30        if !running_pids.is_empty() {
31            return Err(InstanceError::StillRunning {
32                instance_name: self.name().to_string(),
33                pids: running_pids,
34            });
35        }
36
37        tokio::fs::remove_dir_all(self.game_dirs()).await?;
38
39        #[cfg(feature = "events")]
40        {
41            use lighty_event::{Event, InstanceDeletedEvent, EVENT_BUS};
42            use std::time::SystemTime;
43
44            EVENT_BUS.emit(Event::InstanceDeleted(InstanceDeletedEvent {
45                instance_name: self.name().to_string(),
46                timestamp: SystemTime::now(),
47            }));
48        }
49
50        lighty_core::trace_info!(instance = %self.name(), "Instance deleted");
51        Ok(())
52    }
53
54    /// Returns the per-component disk-size breakdown from `version` metadata.
55    fn size_of_instance(&self, version: &Version) -> InstanceSize {
56        let libraries_size = version.libraries.iter().filter_map(|lib| lib.size).sum();
57
58        let mods_size = version
59            .mods
60            .as_ref()
61            .map(|mods| mods.iter().filter_map(|m| m.size).sum())
62            .unwrap_or(0);
63
64        let natives_size = version
65            .natives
66            .as_ref()
67            .map(|natives| natives.iter().filter_map(|n| n.size).sum())
68            .unwrap_or(0);
69
70        let client_size = version.client.as_ref().and_then(|c| c.size).unwrap_or(0);
71
72        let assets_size = version
73            .assets_index
74            .as_ref()
75            .and_then(|idx| idx.total_size)
76            .unwrap_or(0);
77
78        let total = libraries_size + mods_size + natives_size + client_size + assets_size;
79
80        InstanceSize {
81            libraries: libraries_size,
82            mods: mods_size,
83            natives: natives_size,
84            client: client_size,
85            assets: assets_size,
86            total,
87        }
88    }
89}
90
91impl<T: VersionInfo> InstanceControl for T {}