diff --git a/rbx_reflector/plugin.lua b/rbx_reflector/plugin.lua index 652c74f13..0e4313d2a 100644 --- a/rbx_reflector/plugin.lua +++ b/rbx_reflector/plugin.lua @@ -2,4 +2,15 @@ local HttpService = game:GetService("HttpService") local SERVER_URL = "http://localhost:22073" -HttpService:PostAsync(SERVER_URL, "") +local version = string.split(version(), ".") +local major = tonumber(version[1]) +local minor = tonumber(version[2]) +local patch = tonumber(version[3]) +local build = tonumber(version[4]) + +HttpService:PostAsync( + SERVER_URL, + HttpService:JSONEncode({ + version = { major, minor, patch, build }, + }) +) diff --git a/rbx_reflector/src/cli/defaults_place.rs b/rbx_reflector/src/cli/defaults_place.rs index fe5eb7c6e..86c63790b 100644 --- a/rbx_reflector/src/cli/defaults_place.rs +++ b/rbx_reflector/src/cli/defaults_place.rs @@ -13,6 +13,7 @@ use clap::Parser; use innerput::{Innerput, Key, Keyboard}; use notify::{Config, RecommendedWatcher, RecursiveMode, Watcher}; use roblox_install::RobloxStudio; +use serde::Deserialize; use tempfile::tempdir; use tiny_http::Response; @@ -31,7 +32,7 @@ pub struct DefaultsPlaceSubcommand { } impl DefaultsPlaceSubcommand { - pub fn run(&self) -> anyhow::Result<()> { + pub fn run(&self) -> anyhow::Result { if self.output.extension().unwrap_or_default() != "rbxlx" { bail!("The output path must have a .rbxlx extension") } @@ -45,15 +46,15 @@ impl DefaultsPlaceSubcommand { let temp_place_path = temp_dir.path().join("defaults-place.rbxlx"); generate_place_with_all_classes(&temp_place_path, &dump)?; - save_place_in_studio(&temp_place_path)?; + let studio_info = save_place_in_studio(&temp_place_path)?; fs::copy(temp_place_path, &self.output)?; - Ok(()) + Ok(studio_info) } } -fn save_place_in_studio(path: &PathBuf) -> anyhow::Result<()> { +fn save_place_in_studio(path: &PathBuf) -> anyhow::Result { let studio_install = RobloxStudio::locate().context("Could not locate Roblox Studio install")?; @@ -67,7 +68,7 @@ fn save_place_in_studio(path: &PathBuf) -> anyhow::Result<()> { log::info!("Waiting for Roblox Studio to re-save place..."); - plugin_injector.wait_for_response()?; + let studio_info = plugin_injector.wait_for_response()?; let (tx, rx) = mpsc::channel(); let mut watcher = RecommendedWatcher::new(tx, Config::default())?; @@ -97,7 +98,7 @@ fn save_place_in_studio(path: &PathBuf) -> anyhow::Result<()> { studio_process.kill()?; - Ok(()) + Ok(studio_info) } fn generate_place_with_all_classes(path: &PathBuf, dump: &Dump) -> anyhow::Result<()> { @@ -203,6 +204,11 @@ pub struct PluginInjector<'a> { studio_install: &'a RobloxStudio, } +#[derive(Debug, Deserialize)] +pub struct StudioInfo { + pub version: [u32; 4], +} + impl<'a> PluginInjector<'a> { pub fn start(studio_install: &'a RobloxStudio) -> anyhow::Result { let http_server = tiny_http::Server::http("0.0.0.0:22073").unwrap(); @@ -221,15 +227,16 @@ impl<'a> PluginInjector<'a> { }) } - pub fn wait_for_response(self) -> anyhow::Result<()> { - let request = match self.http_server.recv_timeout(Duration::from_secs(30))? { + pub fn wait_for_response(self) -> anyhow::Result { + let mut request = match self.http_server.recv_timeout(Duration::from_secs(30))? { Some(request) => request, None => bail!("Plugin did not send a response within 30 seconds"), }; + let studio_info: StudioInfo = serde_json::from_reader(request.as_reader())?; request.respond(Response::empty(200))?; - Ok(()) + Ok(studio_info) } } diff --git a/rbx_reflector/src/cli/generate.rs b/rbx_reflector/src/cli/generate.rs index b1e64d2e0..3002da680 100644 --- a/rbx_reflector/src/cli/generate.rs +++ b/rbx_reflector/src/cli/generate.rs @@ -19,7 +19,6 @@ use crate::{ api_dump::{Dump, DumpClassMember, Security, Tag, ValueCategory}, defaults::apply_defaults, patches::Patches, - studio_version, }; use super::{defaults_place::DefaultsPlaceSubcommand, dump::DumpSubcommand}; @@ -49,7 +48,7 @@ impl GenerateSubcommand { let contents = fs::read_to_string(&api_dump_path).context("Could not read API dump")?; let dump = serde_json::from_str(&contents).context("Invalid API dump")?; - DefaultsPlaceSubcommand { + let studio_info = DefaultsPlaceSubcommand { api_dump: api_dump_path, output: defaults_place_path.clone(), } @@ -66,7 +65,7 @@ impl GenerateSubcommand { apply_defaults(&mut database, &defaults_place_path)?; - database.version = studio_version::get_studio_version()?; + database.version = studio_info.version; for path in &self.output { let extension = path.extension().unwrap_or_default().to_str(); diff --git a/rbx_reflector/src/cli/mod.rs b/rbx_reflector/src/cli/mod.rs index d098ea8df..576d4c513 100644 --- a/rbx_reflector/src/cli/mod.rs +++ b/rbx_reflector/src/cli/mod.rs @@ -29,7 +29,7 @@ impl Args { pub fn run(&self) -> anyhow::Result<()> { match &self.subcommand { Subcommand::Dump(sub) => sub.run(), - Subcommand::DefaultsPlace(sub) => sub.run(), + Subcommand::DefaultsPlace(sub) => sub.run().map(|_| ()), Subcommand::Generate(sub) => sub.run(), Subcommand::Values(sub) => sub.run(), } diff --git a/rbx_reflector/src/main.rs b/rbx_reflector/src/main.rs index 733de7d9f..2cf7bf98e 100644 --- a/rbx_reflector/src/main.rs +++ b/rbx_reflector/src/main.rs @@ -2,7 +2,6 @@ mod api_dump; mod cli; mod defaults; mod patches; -mod studio_version; use clap::Parser; diff --git a/rbx_reflector/src/studio_version.rs b/rbx_reflector/src/studio_version.rs deleted file mode 100644 index 47157fe03..000000000 --- a/rbx_reflector/src/studio_version.rs +++ /dev/null @@ -1,27 +0,0 @@ -use anyhow::{bail, Context}; -use serde::Deserialize; - -#[derive(Debug, Deserialize)] -struct Response { - version: String, -} - -pub fn get_studio_version() -> anyhow::Result<[u32; 4]> { - let response: Response = - reqwest::blocking::get("https://clientsettings.roblox.com/v2/client-version/WindowsStudio") - .context("Failed to retrieve Studio version")? - .json()?; - - let result = response - .version - .split('.') - .filter_map(|x| x.parse().ok()) - .collect::>() - .try_into(); - - if let Ok(version) = result { - Ok(version) - } else { - bail!("Invalid Studio version: {}", response.version) - } -}