Skip to main content

librojo/cli/
plugin.rs

1use std::{
2    fs::{self, File},
3    io::BufWriter,
4};
5
6use clap::Parser;
7use memofs::{InMemoryFs, Vfs, VfsSnapshot};
8use roblox_install::RobloxStudio;
9
10use crate::serve_session::ServeSession;
11
12static PLUGIN_BINCODE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/plugin.bincode"));
13static PLUGIN_FILE_NAME: &str = "RojoManagedPlugin.rbxm";
14
15/// Install Rojo's plugin.
16#[derive(Debug, Parser)]
17pub struct PluginCommand {
18    #[clap(subcommand)]
19    subcommand: PluginSubcommand,
20}
21
22/// Manages Rojo's Roblox Studio plugin.
23#[derive(Debug, Parser)]
24pub enum PluginSubcommand {
25    /// Install the plugin in Roblox Studio's plugins folder. If the plugin is
26    /// already installed, installing it again will overwrite the current plugin
27    /// file.
28    Install,
29
30    /// Removes the plugin if it is installed.
31    Uninstall,
32}
33
34impl PluginCommand {
35    pub fn run(self) -> anyhow::Result<()> {
36        self.subcommand.run()
37    }
38}
39
40impl PluginSubcommand {
41    pub fn run(self) -> anyhow::Result<()> {
42        match self {
43            PluginSubcommand::Install => install_plugin(),
44            PluginSubcommand::Uninstall => uninstall_plugin(),
45        }
46    }
47}
48
49fn initialize_plugin() -> anyhow::Result<ServeSession> {
50    let plugin_snapshot: VfsSnapshot = bincode::deserialize(PLUGIN_BINCODE)
51        .expect("Rojo's plugin was not properly packed into Rojo's binary");
52
53    let mut in_memory_fs = InMemoryFs::new();
54    in_memory_fs.load_snapshot("/plugin", plugin_snapshot)?;
55
56    let vfs = Vfs::new(in_memory_fs);
57    Ok(ServeSession::new(vfs, "/plugin")?)
58}
59
60fn install_plugin() -> anyhow::Result<()> {
61    let studio = RobloxStudio::locate()?;
62
63    let plugins_folder_path = studio.plugins_path();
64
65    if !plugins_folder_path.exists() {
66        log::debug!("Creating Roblox Studio plugins folder");
67        fs::create_dir(plugins_folder_path)?;
68    }
69
70    let plugin_path = plugins_folder_path.join(PLUGIN_FILE_NAME);
71    log::debug!("Writing plugin to {}", plugin_path.display());
72
73    let mut file = BufWriter::new(File::create(plugin_path)?);
74
75    let session = initialize_plugin()?;
76    let tree = session.tree();
77    let root_id = tree.get_root_id();
78
79    rbx_binary::to_writer(&mut file, tree.inner(), &[root_id])?;
80
81    Ok(())
82}
83
84fn uninstall_plugin() -> anyhow::Result<()> {
85    let studio = RobloxStudio::locate()?;
86
87    let plugin_path = studio.plugins_path().join(PLUGIN_FILE_NAME);
88
89    if plugin_path.exists() {
90        log::debug!("Removing existing plugin from {}", plugin_path.display());
91        fs::remove_file(plugin_path)?;
92    } else {
93        log::debug!("Plugin not installed at {}", plugin_path.display());
94    }
95
96    Ok(())
97}
98
99#[test]
100fn plugin_initialize() {
101    let _ = initialize_plugin().unwrap();
102}