roblox_studio_utils/paths/mod.rs
1use std::{
2 path::{Path, PathBuf},
3 sync::Arc,
4};
5
6use crate::RobloxStudioResult;
7use crate::task::RobloxStudioTask;
8
9#[cfg(target_os = "linux")]
10mod linux;
11#[cfg(target_os = "macos")]
12mod macos;
13#[cfg(target_os = "windows")]
14mod windows;
15
16/**
17 References to discovered, validated paths to the current
18 Roblox Studio executable, content, and plugins directories.
19
20 Can be cheaply cloned and shared between threads.
21*/
22#[derive(Debug, Clone)]
23pub struct RobloxStudioPaths {
24 inner: Arc<RobloxStudioPathsInner>,
25}
26
27impl RobloxStudioPaths {
28 /**
29 Tries to locate the current Roblox Studio installation and directories.
30
31 # Errors
32
33 - If Roblox Studio is not installed.
34 */
35 pub fn new() -> RobloxStudioResult<Self> {
36 RobloxStudioPathsInner::new().map(Self::from)
37 }
38
39 /**
40 Returns the path to the Roblox Studio executable.
41 */
42 #[must_use]
43 pub fn exe(&self) -> &Path {
44 self.inner.exe.as_path()
45 }
46
47 /**
48 Returns the path to the Roblox Studio launcher executable,
49 if one is available.
50 */
51 #[must_use]
52 pub fn launcher(&self) -> Option<&Path> {
53 self.inner.launcher.as_deref()
54 }
55
56 /**
57 Returns the preferred executable path for the given task.
58 */
59 #[must_use]
60 pub(crate) fn exe_for_task(&self, task: Option<RobloxStudioTask>) -> &Path {
61 if cfg!(target_os = "windows")
62 && task.is_some_and(RobloxStudioTask::needs_launcher)
63 && self.inner.launcher.is_some()
64 {
65 self.inner
66 .launcher
67 .as_deref()
68 .expect("launcher path should exist")
69 } else {
70 self.exe()
71 }
72 }
73
74 /**
75 Returns the path to the Roblox Studio content directory.
76
77 This directory contains Roblox bundled assets, in sub-directories such as:
78
79 - `fonts` - bundled font files, typically in OpenType or TrueType format
80 - `sounds` - bundled basic sounds, such as the character reset sound
81 - `textures` - bundled texture files, typically used for `CoreGui`
82 */
83 #[must_use]
84 pub fn content(&self) -> &Path {
85 self.inner.content.as_path()
86 }
87
88 /**
89 Returns the path to the Roblox Studio **user plugins** directory.
90
91 For the path to built-in plugins, see [`RobloxStudioPaths::built_in_plugins`].
92
93 # Warning
94
95 This directory may or may not exist as it is created on demand,
96 either when a user opens it through the Roblox Studio settings,
97 or when they install their first plugin.
98 */
99 #[must_use]
100 pub fn user_plugins(&self) -> &Path {
101 self.inner.plugins_user.as_path()
102 }
103
104 /**
105 Returns the path to the Roblox Studio **built-in plugins** directory.
106
107 These plugins are bundled with Roblox Studio itself, and the directory is guaranteed
108 to exist unlike the user plugins directory ([`RobloxStudioPaths::user_plugins`]).
109 */
110 #[must_use]
111 pub fn built_in_plugins(&self) -> &Path {
112 self.inner.plugins_builtin.as_path()
113 }
114}
115
116// Private inner struct to make RobloxStudioPaths cheaper to clone
117#[derive(Debug, Clone)]
118struct RobloxStudioPathsInner {
119 exe: PathBuf,
120 launcher: Option<PathBuf>,
121 content: PathBuf,
122 plugins_user: PathBuf,
123 plugins_builtin: PathBuf,
124}
125
126impl From<RobloxStudioPathsInner> for RobloxStudioPaths {
127 fn from(inner: RobloxStudioPathsInner) -> Self {
128 Self {
129 inner: Arc::new(inner),
130 }
131 }
132}